<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=2">
<meta name="theme-color" content="#222">
<meta name="generator" content="Hexo 5.3.0">
  <link rel="apple-touch-icon" sizes="180x180" href="/images/apple-touch-icon-next.png">
  <link rel="icon" type="image/png" sizes="32x32" href="/images/favicon-32x32-next.png">
  <link rel="icon" type="image/png" sizes="16x16" href="/images/favicon-16x16-next.png">
  <link rel="mask-icon" href="/images/logo.svg" color="#222">

<link rel="stylesheet" href="/css/main.css">


<link rel="stylesheet" href="/lib/font-awesome/css/all.min.css">

<script id="hexo-configurations">
    var NexT = window.NexT || {};
    var CONFIG = {"hostname":"example.com","root":"/","scheme":"Muse","version":"7.8.0","exturl":false,"sidebar":{"position":"left","display":"post","padding":18,"offset":12,"onmobile":false},"copycode":{"enable":false,"show_result":false,"style":null},"back2top":{"enable":true,"sidebar":false,"scrollpercent":false},"bookmark":{"enable":false,"color":"#222","save":"auto"},"fancybox":false,"mediumzoom":false,"lazyload":false,"pangu":false,"comments":{"style":"tabs","active":null,"storage":true,"lazyload":false,"nav":null},"algolia":{"hits":{"per_page":10},"labels":{"input_placeholder":"Search for Posts","hits_empty":"We didn't find any results for the search: ${query}","hits_stats":"${hits} results found in ${time} ms"}},"localsearch":{"enable":false,"trigger":"auto","top_n_per_article":1,"unescape":false,"preload":false},"motion":{"enable":true,"async":false,"transition":{"post_block":"fadeIn","post_header":"slideDownIn","post_body":"slideDownIn","coll_header":"slideLeftIn","sidebar":"slideUpIn"}}};
  </script>

  <meta property="og:type" content="website">
<meta property="og:title" content="解救Z先生">
<meta property="og:url" content="http://example.com/index.html">
<meta property="og:site_name" content="解救Z先生">
<meta property="og:locale" content="zh_CN">
<meta property="article:author" content="greentree">
<meta name="twitter:card" content="summary">

<link rel="canonical" href="http://example.com/">


<script id="page-configurations">
  // https://hexo.io/docs/variables.html
  CONFIG.page = {
    sidebar: "",
    isHome : true,
    isPost : false,
    lang   : 'zh-CN'
  };
</script>

  <title>解救Z先生</title>
  






  <noscript>
  <style>
  .use-motion .brand,
  .use-motion .menu-item,
  .sidebar-inner,
  .use-motion .post-block,
  .use-motion .pagination,
  .use-motion .comments,
  .use-motion .post-header,
  .use-motion .post-body,
  .use-motion .collection-header { opacity: initial; }

  .use-motion .site-title,
  .use-motion .site-subtitle {
    opacity: initial;
    top: initial;
  }

  .use-motion .logo-line-before i { left: initial; }
  .use-motion .logo-line-after i { right: initial; }
  </style>
</noscript>

</head>

<body itemscope itemtype="http://schema.org/WebPage">
  <div class="container use-motion">
    <div class="headband"></div>

    <header class="header" itemscope itemtype="http://schema.org/WPHeader">
      <div class="header-inner"><div class="site-brand-container">
  <div class="site-nav-toggle">
    <div class="toggle" aria-label="切换导航栏">
      <span class="toggle-line toggle-line-first"></span>
      <span class="toggle-line toggle-line-middle"></span>
      <span class="toggle-line toggle-line-last"></span>
    </div>
  </div>

  <div class="site-meta">

    <a href="/" class="brand" rel="start">
      <span class="logo-line-before"><i></i></span>
      <h1 class="site-title">解救Z先生</h1>
      <span class="logo-line-after"><i></i></span>
    </a>
  </div>

  <div class="site-nav-right">
    <div class="toggle popup-trigger">
    </div>
  </div>
</div>




<nav class="site-nav">
  <ul id="menu" class="main-menu menu">
        <li class="menu-item menu-item-home">

    <a href="/" rel="section"><i class="fa fa-home fa-fw"></i>首页</a>

  </li>
        <li class="menu-item menu-item-about">

    <a href="/aboutme/" rel="section"><i class="fa fa-user fa-fw"></i>关于</a>

  </li>
        <li class="menu-item menu-item-archives">

    <a href="/archives/" rel="section"><i class="fa fa-archive fa-fw"></i>归档</a>

  </li>
  </ul>
</nav>




</div>
    </header>

    
  <div class="back-to-top">
    <i class="fa fa-arrow-up"></i>
    <span>0%</span>
  </div>


    <main class="main">
      <div class="main-inner">
        <div class="content-wrap">
          

          <div class="content index posts-expand">
            
      
  
  
  <article itemscope itemtype="http://schema.org/Article" class="post-block" lang="zh-CN">
    <link itemprop="mainEntityOfPage" href="http://example.com/2021/01/24/nexus-3-29-x%E7%A7%81%E6%9C%8D%E7%AE%80%E6%98%8E%E5%AE%89%E8%A3%85%E9%85%8D%E7%BD%AE/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="image" content="/images/avatar.gif">
      <meta itemprop="name" content="greentree">
      <meta itemprop="description" content="">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="解救Z先生">
    </span>
      <header class="post-header">
        <h2 class="post-title" itemprop="name headline">
          
            <a href="/2021/01/24/nexus-3-29-x%E7%A7%81%E6%9C%8D%E7%AE%80%E6%98%8E%E5%AE%89%E8%A3%85%E9%85%8D%E7%BD%AE/" class="post-title-link" itemprop="url">nexus-3.29.x私服简明安装配置</a>
        </h2>

        <div class="post-meta">
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="far fa-calendar"></i>
              </span>
              <span class="post-meta-item-text">发表于</span>

              <time title="创建时间：2021-01-24 12:24:11" itemprop="dateCreated datePublished" datetime="2021-01-24T12:24:11+08:00">2021-01-24</time>
            </span>
              <span class="post-meta-item">
                <span class="post-meta-item-icon">
                  <i class="far fa-calendar-check"></i>
                </span>
                <span class="post-meta-item-text">更新于</span>
                <time title="修改时间：2021-03-17 22:53:16" itemprop="dateModified" datetime="2021-03-17T22:53:16+08:00">2021-03-17</time>
              </span>

          

        </div>
      </header>

    
    
    
    <div class="post-body" itemprop="articleBody">

      
          <h1 id="Maven私服Nexus3-x环境构建操作记录"><a href="#Maven私服Nexus3-x环境构建操作记录" class="headerlink" title="Maven私服Nexus3.x环境构建操作记录"></a>Maven私服Nexus3.x环境构建操作记录</h1><h3 id="Maven介绍"><a href="#Maven介绍" class="headerlink" title="Maven介绍"></a>Maven介绍</h3><p>Apache Maven是一个创新的软件项目管理和综合工具。<br>Maven提供了一个基于项目对象模型（POM）文件的新概念来管理项目的构建，可以从一个中心资料片管理项目构建，报告和文件。<br>Maven最强大的功能就是能够自动下载项目依赖库。<br>Maven提供了开发人员构建一个完整的生命周期框架。开发团队可以自动完成项目的基础工具建设，Maven使用标准的目录结构和默认构建生命周期。<br>在多个开发团队环境时，Maven可以设置按标准在非常短的时间里完成配置工作。由于大部分项目的设置都很简单，并且可重复使用，Maven让开发人员的工作更轻松，同时创建报表，检查，构建和测试自动化设置。<br>Maven项目的结构和内容在一个XML文件中声明，pom.xml 项目对象模型（POM），这是整个Maven系统的基本单元。</p>
<p>Maven提供了开发人员的方式来管理：<br>1）Builds<br>2）Documentation<br>3）Reporting<br>4）Dependencies<br>5）SCMs<br>6）Releases<br>7）Distribution<br>8）mailing list<br>概括地说，Maven简化和标准化项目建设过程。处理编译，分配，文档，团队协作和其他任务的无缝连接。<br>Maven增加可重用性并负责建立相关的任务。<br>Maven最初设计，是以简化Jakarta Turbine项目的建设。在几个项目，每个项目包含了不同的Ant构建文件。 JAR检查到CVS。<br>Apache组织开发Maven可以建立多个项目，发布项目信息，项目部署，在几个项目中JAR文件提供团队合作和帮助。</p>
<p>Maven主要目标是提供给开发人员：<br>1）项目是可重复使用，易维护，更容易理解的一个综合模型。<br>2）插件或交互的工具，这种声明性的模式。</p>
<h3 id="私服介绍"><a href="#私服介绍" class="headerlink" title="私服介绍"></a>私服介绍</h3><p>私服是指私有服务器，是架设在局域网的一种特殊的远程仓库，目的是代理远程仓库及部署第三方构建。有了私服之后，当 Maven 需要下载构件时，直接请求私服，私服上存在则下载到本地仓库；否则，私服请求外部的远程仓库，将构件下载到私服，再提供给本地仓库下载。</p>
<h3 id="Nexus介绍"><a href="#Nexus介绍" class="headerlink" title="Nexus介绍"></a>Nexus介绍</h3><p>Nexus是一个强大的Maven仓库管理器，它极大地简化了本地内部仓库的维护和外部仓库的访问。<br>如果使用了公共的Maven仓库服务器，可以从Maven中央仓库下载所需要的构件（Artifact），但这通常不是一个好的做法。<br>正常做法是在本地架设一个Maven仓库服务器，即利用Nexus私服可以只在一个地方就能够完全控制访问和部署在你所维护仓库中的每个Artifact。<br>Nexus在代理远程仓库的同时维护本地仓库，以降低中央仓库的负荷,节省外网带宽和时间，Nexus私服就可以满足这样的需要。<br>Nexus是一套“开箱即用”的系统不需要数据库，它使用文件系统加Lucene来组织数据。<br>Nexus使用ExtJS来开发界面，利用Restlet来提供完整的REST APIs，通过m2eclipse与Eclipse集成使用。<br>Nexus支持WebDAV与LDAP安全身份认证。<br>Nexus还提供了强大的仓库管理功能，构件搜索功能，它基于REST，友好的UI是一个extjs的REST客户端，它占用较少的内存，基于简单文件系统而非数据库。</p>
<p>为什么要构建Nexus私服？<br>如果没有Nexus私服，我们所需的所有构件都需要通过maven的中央仓库和第三方的Maven仓库下载到本地，而一个团队中的所有人都重复的从maven仓库下载构件无疑加大了仓库的负载和浪费了外网带宽，如果网速慢的话，还会影响项目的进程。很多情况下项目的开发都是在内网进行的，连接不到maven仓库怎么办呢？开发的公共构件怎么让其它项目使用？这个时候我们不得不为自己的团队搭建属于自己的maven私服，这样既节省了网络带宽也会加速项目搭建的进程，当然前提条件就是你的私服中拥有项目所需的所有构件。</p>
<p>总之，在本地构建nexus私服的好处有：<br>1）加速构建；<br>2）节省带宽；<br>3）节省中央maven仓库的带宽；<br>4）稳定（应付一旦中央服务器出问题的情况）；<br>5）控制和审计；<br>6）能够部署第三方构件；<br>7）可以建立本地内部仓库；<br>8）可以建立公共仓库<br>这些优点使得Nexus日趋成为最流行的Maven仓库管理器。</p>
<h3 id="Maven安装"><a href="#Maven安装" class="headerlink" title="Maven安装"></a>Maven安装</h3><h3 id="Nexus安装"><a href="#Nexus安装" class="headerlink" title="Nexus安装"></a>Nexus安装</h3><p>如果运行出错：</p>
<p>解决方案：nexus 所需文件夹 放入英文目录下  比如  D:\nexus\nexus-3.13.0-01\bin\nexus.exe /run 就可以了</p>
<p><a target="_blank" rel="noopener" href="http://localhost:8081/#browse/welcome">http://localhost:8081/#browse/welcome</a></p>
<p>登录密码： admin/***8460p</p>
<p><strong>补充一点：在实际的开发中我们需要把nexus私服注册成为服务，方便我们的开发</strong></p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">C:\nexus-3.29.2-02-win64\nexus-3.29.2-02\bin  #中文路径会导致运行失败</span><br><span class="line"></span><br><span class="line">nexus.exe &#x2F;install &lt;optional-service-name&gt; #安装</span><br><span class="line">nexus.exe &#x2F;start &lt;optional-service-name&gt; #开始</span><br><span class="line">nexus.exe &#x2F;stop &lt;optional-service-name&gt; #结束</span><br><span class="line">nexus.exe &#x2F;uninstall &lt;optional-service-name&gt; #卸载</span><br></pre></td></tr></table></figure>
<h4 id="Maven库的类型"><a href="#Maven库的类型" class="headerlink" title="Maven库的类型"></a>Maven库的类型</h4><p>maven-central：maven中央库，默认从<a target="_blank" rel="noopener" href="https://repo1.maven.org/maven2/%E6%8B%89%E5%8F%96jar">https://repo1.maven.org/maven2/拉取jar</a><br>maven-releases：私库发行版jar<br>maven-snapshots：私库快照（调试版本）jar<br>maven-public：仓库分组，把上面三个仓库组合在一起对外提供服务，在本地maven基础配置settings.xml中使用。</p>
<table>
<thead>
<tr>
<th align="left">项目</th>
<th align="left">具体说明</th>
</tr>
</thead>
<tbody><tr>
<td align="left">hosted</td>
<td align="left">本地存储。像官方仓库一样提供本地私库功能</td>
</tr>
<tr>
<td align="left">proxy</td>
<td align="left">提供代理其它仓库的类型</td>
</tr>
<tr>
<td align="left">group</td>
<td align="left">组类型，能够组合多个仓库为一个地址提供服务</td>
</tr>
</tbody></table>
<h4 id="Maven-aliyun-代理"><a href="#Maven-aliyun-代理" class="headerlink" title="Maven aliyun 代理"></a>Maven aliyun 代理</h4><p><a target="_blank" rel="noopener" href="https://help.aliyun.com/document_detail/102512.html">https://help.aliyun.com/document_detail/102512.html</a></p>
<h4 id="Maven-settings设置"><a href="#Maven-settings设置" class="headerlink" title="Maven settings设置"></a>Maven settings设置</h4><p>mvn -X</p>
<p>mvn install</p>
<p>mvn deploy</p>
<p>.m2/settings.xml</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line">	<span class="tag">&lt;<span class="name">server</span>&gt;</span></span><br><span class="line">      <span class="tag">&lt;<span class="name">id</span>&gt;</span>nexus<span class="tag">&lt;/<span class="name">id</span>&gt;</span></span><br><span class="line">      <span class="tag">&lt;<span class="name">username</span>&gt;</span>admin<span class="tag">&lt;/<span class="name">username</span>&gt;</span></span><br><span class="line">      <span class="tag">&lt;<span class="name">password</span>&gt;</span>***8460p<span class="tag">&lt;/<span class="name">password</span>&gt;</span></span><br><span class="line">     <span class="tag">&lt;/<span class="name">server</span>&gt;</span>	</span><br><span class="line"></span><br><span class="line">	<span class="tag">&lt;<span class="name">mirror</span>&gt;</span></span><br><span class="line">	    <span class="tag">&lt;<span class="name">id</span>&gt;</span>aliyunmaven<span class="tag">&lt;/<span class="name">id</span>&gt;</span></span><br><span class="line">	    <span class="tag">&lt;<span class="name">mirrorOf</span>&gt;</span>central<span class="tag">&lt;/<span class="name">mirrorOf</span>&gt;</span></span><br><span class="line">	    <span class="tag">&lt;<span class="name">name</span>&gt;</span>阿里云公共仓库1<span class="tag">&lt;/<span class="name">name</span>&gt;</span></span><br><span class="line"><span class="comment">&lt;!--</span></span><br><span class="line"><span class="comment">		&lt;url&gt;https://maven.aliyun.com/repository/central&lt;/url&gt; </span></span><br><span class="line"><span class="comment">--&gt;</span></span><br><span class="line">	    <span class="tag">&lt;<span class="name">url</span>&gt;</span>http://192.168.1.8:8081/repository/maven-central<span class="tag">&lt;/<span class="name">url</span>&gt;</span> </span><br><span class="line">	<span class="tag">&lt;/<span class="name">mirror</span>&gt;</span></span><br></pre></td></tr></table></figure>
<h3 id="参考文章"><a href="#参考文章" class="headerlink" title="参考文章"></a>参考文章</h3><ol>
<li>主要参考文章： <a target="_blank" rel="noopener" href="https://www.cnblogs.com/kevingrace/p/6201984.html">https://www.cnblogs.com/kevingrace/p/6201984.html</a></li>
<li>**nexus-3.29.x私服简明安装配置(windows)**： <a target="_blank" rel="noopener" href="https://www.jianshu.com/p/1d2041f62900">https://www.jianshu.com/p/1d2041f62900</a></li>
</ol>
<h3 id="Note"><a href="#Note" class="headerlink" title="Note"></a>Note</h3><p>Nexus Repository Manager 3.2 does NOT support usage of remote index for searches (and other purposes) at all. If you want this feature I suggest to stick with Nexus Repository Manager 2 for now.</p>

      
    </div>

    
    
    
      <footer class="post-footer">
        <div class="post-eof"></div>
      </footer>
  </article>
  
  
  

      
  
  
  <article itemscope itemtype="http://schema.org/Article" class="post-block" lang="zh-CN">
    <link itemprop="mainEntityOfPage" href="http://example.com/2021/01/17/ubuntu20-04LTS%E6%9B%B4%E6%8D%A2%E9%98%BF%E9%87%8C%E4%BA%91%E6%BA%90/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="image" content="/images/avatar.gif">
      <meta itemprop="name" content="greentree">
      <meta itemprop="description" content="">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="解救Z先生">
    </span>
      <header class="post-header">
        <h2 class="post-title" itemprop="name headline">
          
            <a href="/2021/01/17/ubuntu20-04LTS%E6%9B%B4%E6%8D%A2%E9%98%BF%E9%87%8C%E4%BA%91%E6%BA%90/" class="post-title-link" itemprop="url">ubuntu20.04LTS更换阿里云源</a>
        </h2>

        <div class="post-meta">
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="far fa-calendar"></i>
              </span>
              <span class="post-meta-item-text">发表于</span>
              

              <time title="创建时间：2021-01-17 15:58:23 / 修改时间：16:00:20" itemprop="dateCreated datePublished" datetime="2021-01-17T15:58:23+08:00">2021-01-17</time>
            </span>

          

        </div>
      </header>

    
    
    
    <div class="post-body" itemprop="articleBody">

      
          <p>第一步：先备份下原始源：</p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">sudo cp /etc/apt/sources.list /etc/apt/sources.list.backup</span><br></pre></td></tr></table></figure>
<p>第二步：修改文件  </p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">sudo vim  /etc/apt/sources.list</span><br></pre></td></tr></table></figure>
<p>清除原有的，替换以下源</p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">deb http://mirrors.aliyun.com/ubuntu/ focal main restricted</span><br><span class="line">deb http://mirrors.aliyun.com/ubuntu/ focal-updates main restricted</span><br><span class="line">deb http://mirrors.aliyun.com/ubuntu/ focal universe</span><br><span class="line">deb http://mirrors.aliyun.com/ubuntu/ focal-updates universe</span><br><span class="line">deb http://mirrors.aliyun.com/ubuntu/ focal multiverse</span><br><span class="line">deb http://mirrors.aliyun.com/ubuntu/ focal-updates multiverse</span><br><span class="line">deb http://mirrors.aliyun.com/ubuntu/ focal-backports main restricted universe multiverse</span><br><span class="line">deb http://mirrors.aliyun.com/ubuntu/ focal-security main restricted</span><br><span class="line">deb http://mirrors.aliyun.com/ubuntu/ focal-security universe</span><br><span class="line">deb http://mirrors.aliyun.com/ubuntu/ focal-security multiverse</span><br></pre></td></tr></table></figure>
<p> 保存下，即可执行更新</p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">sudo  apt update</span><br><span class="line">sudo  apt upgrade</span><br></pre></td></tr></table></figure>

      
    </div>

    
    
    
      <footer class="post-footer">
        <div class="post-eof"></div>
      </footer>
  </article>
  
  
  

      
  
  
  <article itemscope itemtype="http://schema.org/Article" class="post-block" lang="zh-CN">
    <link itemprop="mainEntityOfPage" href="http://example.com/2021/01/17/samba%E6%9C%8D%E5%8A%A1%E9%85%8D%E7%BD%AE/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="image" content="/images/avatar.gif">
      <meta itemprop="name" content="greentree">
      <meta itemprop="description" content="">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="解救Z先生">
    </span>
      <header class="post-header">
        <h2 class="post-title" itemprop="name headline">
          
            <a href="/2021/01/17/samba%E6%9C%8D%E5%8A%A1%E9%85%8D%E7%BD%AE/" class="post-title-link" itemprop="url">samba服务配置</a>
        </h2>

        <div class="post-meta">
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="far fa-calendar"></i>
              </span>
              <span class="post-meta-item-text">发表于</span>
              

              <time title="创建时间：2021-01-17 15:57:27 / 修改时间：16:00:01" itemprop="dateCreated datePublished" datetime="2021-01-17T15:57:27+08:00">2021-01-17</time>
            </span>

          

        </div>
      </header>

    
    
    
    <div class="post-body" itemprop="articleBody">

      
          <h1 id="Samba配置-使每个用户可以用自己的用户名和密码登录自己的home目录"><a href="#Samba配置-使每个用户可以用自己的用户名和密码登录自己的home目录" class="headerlink" title="Samba配置 - 使每个用户可以用自己的用户名和密码登录自己的home目录"></a>Samba配置 - 使每个用户可以用自己的用户名和密码登录自己的home目录</h1><h3 id="修改配置文件"><a href="#修改配置文件" class="headerlink" title="修改配置文件"></a>修改配置文件</h3><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">sudo vi /etc/samba/smb.conf</span><br></pre></td></tr></table></figure>
<p>找到[homes]项，此项默认是注释掉的，取消其注释，然后修改其具体内容，修改成如下：</p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#</span><span class="bash">======================= Share Definitions =======================</span></span><br><span class="line"></span><br><span class="line"><span class="meta">#</span><span class="bash"> Un-comment the following (and tweak the other settings below to suit)</span></span><br><span class="line"><span class="meta">#</span><span class="bash"> to <span class="built_in">enable</span> the default home directory shares. This will share each</span></span><br><span class="line"><span class="meta">#</span><span class="bash"> user<span class="string">&#x27;s home directory as \\server\username</span></span></span><br><span class="line">[homes]</span><br><span class="line">   comment = Home Directories</span><br><span class="line">   browseable = yes</span><br><span class="line"></span><br><span class="line"><span class="meta">#</span><span class="bash"> By default, the home directories are exported read-only. Change the</span></span><br><span class="line"><span class="meta">#</span><span class="bash"> next parameter to <span class="string">&#x27;no&#x27;</span> <span class="keyword">if</span> you want to be able to write to them.</span></span><br><span class="line">   read only = no</span><br><span class="line"></span><br><span class="line"><span class="meta">#</span><span class="bash"> File creation mask is <span class="built_in">set</span> to 0700 <span class="keyword">for</span> security reasons. If you want to</span></span><br><span class="line"><span class="meta">#</span><span class="bash"> create files with group=rw permissions, <span class="built_in">set</span> next parameter to 0775.</span></span><br><span class="line">   create mask = 0755</span><br><span class="line"></span><br><span class="line"><span class="meta">#</span><span class="bash"> Directory creation mask is <span class="built_in">set</span> to 0700 <span class="keyword">for</span> security reasons. If you want to</span></span><br><span class="line"><span class="meta">#</span><span class="bash"> create <span class="built_in">dirs</span>. with group=rw permissions, <span class="built_in">set</span> next parameter to 0775.</span></span><br><span class="line">   directory mask = 0755</span><br><span class="line"></span><br><span class="line"><span class="meta">#</span><span class="bash"> By default, \\server\username shares can be connected to by anyone</span></span><br><span class="line"><span class="meta">#</span><span class="bash"> with access to the samba server.</span></span><br><span class="line"><span class="meta">#</span><span class="bash"> Un-comment the following parameter to make sure that only <span class="string">&quot;username&quot;</span></span></span><br><span class="line"><span class="meta">#</span><span class="bash"> can connect to \\server\username</span></span><br><span class="line"><span class="meta">#</span><span class="bash"> This might need tweaking when using external authentication schemes</span></span><br><span class="line">   valid users = %S</span><br></pre></td></tr></table></figure>
<h3 id="重启samba服务"><a href="#重启samba服务" class="headerlink" title="重启samba服务"></a>重启samba服务</h3><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">service smbd restart</span><br></pre></td></tr></table></figure>
<h3 id="增加一个现有用户的对应samba帐号"><a href="#增加一个现有用户的对应samba帐号" class="headerlink" title="增加一个现有用户的对应samba帐号"></a>增加一个现有用户的对应samba帐号</h3><p>如我已经有一个用户叫zhaodong，现在给zhaodong开通samba帐号：</p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">sudo smbpasswd -a zhaodong  </span><br></pre></td></tr></table></figure>
<p>根据提示输入两次密码即可。</p>
<h3 id="在Window下输入samba地址尝试登录"><a href="#在Window下输入samba地址尝试登录" class="headerlink" title="在Window下输入samba地址尝试登录"></a>在Window下输入samba地址尝试登录</h3><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">\\192.168.1.19\zhaodong</span><br></pre></td></tr></table></figure>
<p>此时windows应该会弹出窗口要求输入用户名和密码了</p>
<h3 id="参考实现"><a href="#参考实现" class="headerlink" title="参考实现"></a>参考实现</h3><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line">[coresat]</span><br><span class="line">comment = share folder</span><br><span class="line">browseable = yes</span><br><span class="line">path = /home/coresat/</span><br><span class="line">create mask = 0700</span><br><span class="line">directory mask = 0700</span><br><span class="line">valid users = coresat</span><br><span class="line">force user = coresat</span><br><span class="line">force group = coresat</span><br><span class="line">public = yes</span><br><span class="line">available = yes</span><br><span class="line">writable = yes</span><br></pre></td></tr></table></figure>
<h3 id="参考文章"><a href="#参考文章" class="headerlink" title="参考文章"></a>参考文章</h3><p><a target="_blank" rel="noopener" href="https://ubuntu.com/tutorials/install-and-configure-samba#1-overview">https://ubuntu.com/tutorials/install-and-configure-samba#1-overview</a></p>

      
    </div>

    
    
    
      <footer class="post-footer">
        <div class="post-eof"></div>
      </footer>
  </article>
  
  
  

      
  
  
  <article itemscope itemtype="http://schema.org/Article" class="post-block" lang="zh-CN">
    <link itemprop="mainEntityOfPage" href="http://example.com/2021/01/17/%E7%AE%97%E6%B3%95%E5%A4%8D%E6%9D%82%E5%BA%A6/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="image" content="/images/avatar.gif">
      <meta itemprop="name" content="greentree">
      <meta itemprop="description" content="">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="解救Z先生">
    </span>
      <header class="post-header">
        <h2 class="post-title" itemprop="name headline">
          
            <a href="/2021/01/17/%E7%AE%97%E6%B3%95%E5%A4%8D%E6%9D%82%E5%BA%A6/" class="post-title-link" itemprop="url">算法复杂度</a>
        </h2>

        <div class="post-meta">
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="far fa-calendar"></i>
              </span>
              <span class="post-meta-item-text">发表于</span>
              

              <time title="创建时间：2021-01-17 01:14:15 / 修改时间：01:46:27" itemprop="dateCreated datePublished" datetime="2021-01-17T01:14:15+08:00">2021-01-17</time>
            </span>

          

        </div>
      </header>

    
    
    
    <div class="post-body" itemprop="articleBody">

      
          <h1 id="算法复杂度和NP问题"><a href="#算法复杂度和NP问题" class="headerlink" title="算法复杂度和NP问题"></a>算法复杂度和NP问题</h1><h3 id="时间复杂度"><a href="#时间复杂度" class="headerlink" title="时间复杂度"></a>时间复杂度</h3><p>大O表示法是一种特殊的表示法，指出了算法的速度有多快。大O表示法让你能够比较操作数，它指出了算法运行时间的增速。大O表示法指出了最糟情况下的运行时间。</p>
<img src="/2021/01/17/%E7%AE%97%E6%B3%95%E5%A4%8D%E6%9D%82%E5%BA%A6/image-2021-01-16-14.11.27@2x.png" class title="title text" alt="alt text">

<p>时间复杂度并不是表示一个程序解决问题需要花多少时间，而是当问题规模扩大后，程序需要的时间长度增长得有多快。也就是说，对于高速处理数据的计算机来说，处理某一个特定数据的效率不能衡量一个程序的好坏，而应该看当这个数据的规模变大到数百倍后，程序运行时间是否还是一样，或者也跟着慢了数百倍，或者变慢了数万倍。不管数据有多大，程序处理花的时间始终是那么多的，我们就说这个程序很好，<strong>具有O(1)的时间复杂度，也称常数级复杂度</strong>；数据规模变得有多大，花的时间也跟着变得有多长，这个程序的**时间复杂度就是O(n)**，比如找n个数中的最大值；而像冒泡排序、插入排序等，数据扩大2倍，时间变慢4倍的，属于O(n^2)的复杂度。还有一些穷举类的算法，所需时间长度成几何阶数上涨，这就是O(a^n)的指数级复杂度，甚至O(n!)的阶乘级复杂度。不会存在O(2n^2)的复杂度，因为前面的那个“2”是系数，根本不会影响到整个程序的时间增长。同样地，O (n^3+n^2)的复杂度也就是O(n^3)的复杂度。因此，我们会说，一个O(0.01n^3)的程序的效率比O(100n^2)的效率低，尽管在n很小的时候，前者优于后者，但后者时间随数据规模增长得慢，最终O(n^3)的复杂度将远远超过O(n^2)。我们也说，O(n^100)的复杂度小于O(1.01^n)的复杂度。</p>
<p>容易看出，前面的几类复杂度被分为两种级别，其中后者的复杂度无论如何都远远大于前者：一种是O(1),O(log(n)),O(n^a)等，我们把它叫做<strong>多项式级的复杂度</strong>，因为它的规模n出现在底数的位置；另一种是O(a^n)和O(n!)型复杂度，它是<strong>非多项式级的，其复杂度计算机往往不能承受</strong>。<strong>当我们在解决一个问题时，我们选择的算法通常都需要是多项式级的复杂度，非多项式级的复杂度需要的时间太多</strong>，往往会超时，除非是数据规模非常小。</p>
<p>自然地，人们会想到一个问题：**会不会所有的问题都可以找到复杂度为多项式级的算法呢？很遗憾，答案是否定的。有些问题甚至根本不可能找到一个正确的算法来，这称之为“不可解问题”(Undecidable Decision Problem)**。<a target="_blank" rel="noopener" href="http://www.matrix67.com/blog/article.asp?id=62">The Halting Problem</a>就是一个著名的不可解问题，在我的Blog上有过专门的介绍和证明。再比如，输出从1到n这n个数的全排列。不管你用什么方法，你的复杂度都是阶乘级，因为你总得用阶乘级的时间打印出结果来。有人说，这样的“问题”不是一个“正规”的问题，正规的问题是让程序解决一个问题，输出一个“YES”或“NO”（这被称为判定性问题），或者一个什么什么的最优值（这被称为最优化问题）。那么，根据这个定义，我也能举出一个不大可能会有多项式级算法的问题来：Hamilton回路。问题是这样的：给你一个图，问你能否找到一条经过每个顶点一次且恰好一次（不遗漏也不重复）最后又走回来的路（满足这个条件的路径叫做Hamilton回路）。这个问题现在还没有找到多项式级的算法。事实上，这个问题就是我们后面要说的NPC问题。</p>
<h3 id="P类问题的概念"><a href="#P类问题的概念" class="headerlink" title="P类问题的概念"></a>P类问题的概念</h3><p>下面引入P类问题的概念：<strong>如果一个问题可以找到一个能在多项式的时间里解决它的算法，那么这个问题就属于P问题</strong>。P是英文单词多项式的第一个字母。哪些问题是P类问题呢？通常NOI和NOIP不会出不属于P类问题的题目。我们常见到的一些信息奥赛的题目都是P问题。<strong>道理很简单，一个用穷举换来的非多项式级时间的超时程序不会涵盖任何有价值的算法</strong>。</p>
<h3 id="NP问题的概念"><a href="#NP问题的概念" class="headerlink" title="NP问题的概念"></a>NP问题的概念</h3><p>接下来引入NP问题的概念。这个就有点难理解了，或者说容易理解错误。在这里强调（回到我竭力想澄清的误区上），NP问题不是非P类问题。<strong>NP问题是指可以在多项式的时间里验证一个解的问题。NP问题的另一个定义是，可以在多项式的时间里猜出一个解的问题。</strong>比方说，我RP很好，在程序中需要枚举时，我可以一猜一个准。现在某人拿到了一个求最短路径的问题，问从起点到终点是否有一条小于100个单位长度的路线。它根据数据画好了图，但怎么也算不出来，于是来问我：你看怎么选条路走得最少？我说，我RP很好，肯定能随便给你指条很短的路出来。然后我就胡乱画了几条线，说就这条吧。那人按我指的这条把权值加起来一看，嘿，神了，路径长度98，比100小。于是答案出来了，存在比100小的路径。别人会问他这题怎么做出来的，他就可以说，因为我找到了一个比100 小的解。在这个题中，找一个解很困难，但验证一个解很容易。验证一个解只需要O(n)的时间复杂度，也就是说我可以花O(n)的时间把我猜的路径的长度加出来。那么，只要我RP好，猜得准，我一定能在多项式的时间里解决这个问题。我猜到的方案总是最优的，不满足题意的方案也不会来骗我去选它。这就是NP问题。当然有不是NP问题的问题，即你猜到了解但是没用，因为你不能在多项式的时间里去验证它。下面我要举的例子是一个经典的例子，它指出了一个目前还没有办法在多项式的时间里验证一个解的问题。很显然，前面所说的Hamilton回路是NP问题，因为验证一条路是否恰好经过了每一个顶点非常容易。但我要把问题换成这样：试问一个图中是否不存在Hamilton回路。这样问题就没法在多项式的时间里进行验证了，因为除非你试过所有的路，否则你不敢断定它“没有Hamilton回路”。</p>
<p> <strong>之所以要定义NP问题，是因为通常只有NP问题才可能找到多项式的算法。</strong>我们不会指望一个连多项式地验证一个解都不行的问题存在一个解决它的多项式级的算法。相信读者很快明白，信息学中的号称最困难的问题——“NP问题”，实际上是在探讨NP问题与P类问题的关系。</p>
<p>很显然，所有的P类问题都是NP问题。也就是说，能多项式地解决一个问题，必然能多项式地验证一个问题的解——既然正解都出来了，验证任意给定的解也只需要比较一下就可以了。关键是，人们想知道，是否所有的NP问题都是P类问题。我们可以再用集合的观点来说明。如果把所有P类问题归为一个集合P中，把所有 NP问题划进另一个集合NP中，那么，显然有P属于NP。现在，所有对NP问题的研究都集中在一个问题上，即究竟是否有P=NP？通常所谓的“NP问题”，其实就一句话：证明或推翻P=NP。<br>NP问题一直都是信息学的巅峰。巅峰，意即很引人注目但难以解决。在信息学研究中，这是一个耗费了很多时间和精力也没有解决的终极问题，好比物理学中的大统一和数学中的歌德巴赫猜想等。<br>目前为止这个问题还“啃不动”。但是，一个总的趋势、一个大方向是有的。人们普遍认为，P=NP不成立，也就是说，多数人相信，存在至少一个不可能有多项式级复杂度的算法的NP问题。人们如此坚信P≠NP是有原因的，就是在研究NP问题的过程中找出了一类非常特殊的NP问题叫做NP-完全问题，也即所谓的 NPC问题。C是英文单词“完全”的第一个字母。正是NPC问题的存在，使人们相信P≠NP。下文将花大量篇幅介绍NPC问题，你从中可以体会到NPC问题使P=NP变得多么不可思议。</p>
<h3 id="NPC问题"><a href="#NPC问题" class="headerlink" title="NPC问题"></a>NPC问题</h3><p>为了说明NPC问题，我们先引入一个概念——约化(Reducibility，有的资料上叫“归约”)。简单地说，一个问题A可以约化为问题B的含义即是，可以用问题B的解法解决问题A，或者说，问题A可以“变成”问题B。《算法导论》上举了这么一个例子。比如说，现在有两个问题：求解一个一元一次方程和求解一个一元二次方程。那么我们说，前者可以约化为后者，意即知道如何解一个一元二次方程那么一定能解出一元一次方程。我们可以写出两个程序分别对应两个问题，那么我们能找到一个“规则”，按照这个规则把解一元一次方程程序的输入数据变一下，用在解一元二次方程的程序上，两个程序总能得到一样的结果。这个规则即是：两个方程的对应项系数不变，一元二次方程的二次项系数为0。按照这个规则把前一个问题转换成后一个问题，两个问题就等价了。同样地，我们可以说，Hamilton回路可以约化为TSP问题(Travelling Salesman Problem，旅行商问题)：在Hamilton回路问题中，两点相连即这两点距离为0，两点不直接相连则令其距离为1，于是问题转化为在TSP问题中，是否存在一条长为0的路径。Hamilton回路存在当且仅当TSP问题中存在长为0的回路。</p>
<p>“问题A可约化为问题B”有一个重要的直观意义：B的时间复杂度高于或者等于A的时间复杂度。也就是说，问题A不比问题B难。这很容易理解。既然问题A能用问题B来解决，倘若B的时间复杂度比A的时间复杂度还低了，那A的算法就可以改进为B的算法，两者的时间复杂度还是相同。正如解一元二次方程比解一元一次方程难，因为解决前者的方法可以用来解决后者。</p>
<p>很显然，约化具有一项重要的性质：约化具有传递性。如果问题A可约化为问题B，问题B可约化为问题C，则问题A一定可约化为问题C。这个道理非常简单，就不必阐述了。<br>现在再来说一下约化的标准概念就不难理解了：如果能找到这样一个变化法则，对任意一个程序A的输入，都能按这个法则变换成程序B的输入，使两程序的输出相同，那么我们说，问题A可约化为问题B。当然，我们所说的“可约化”是指的可“多项式地”约化(Polynomial-time Reducible)，即变换输入的方法是能在多项式的时间里完成的。约化的过程只有用多项式的时间完成才有意义。</p>
<p>好了，<strong>从约化的定义中我们看到，一个问题约化为另一个问题，时间复杂度增加了，问题的应用范围也增大了。通过对某些问题的不断约化，我们能够不断寻找复杂度更高，但应用范围更广的算法来代替复杂度虽然低，但只能用于很小的一类问题的算法。</strong>再回想前面讲的P和NP问题，联想起约化的传递性，自然地，我们会想问，<strong>如果不断地约化上去，不断找到能“通吃”若干小NP问题的一个稍复杂的大NP问题，那么最后是否有可能找到一个时间复杂度最高，并且能“通吃”所有的 NP问题的这样一个超级NP问题？答案居然是肯定的。也就是说，存在这样一个NP问题，所有的NP问题都可以约化成它。换句话说，只要解决了这个问题，那么所有的NP问题都解决了。</strong>这种问题的存在难以置信，并且更加不可思议的是，<strong>这种问题不只一个，它有很多个，它是一类问题。这一类问题就是传说中的NPC 问题，也就是NP-完全问题。</strong>NPC问题的出现使整个NP问题的研究得到了飞跃式的发展。我们有理由相信，NPC问题是最复杂的问题。再次回到全文开头，我们可以看到，人们想表达一个问题不存在多项式的高效算法时应该说它“属于NPC问题”。此时，我的目的终于达到了，我已经把NP问题和NPC问题区别开了。到此为止，本文已经写了近5000字了，我佩服你还能看到这里来，同时也佩服一下自己能写到这里来。</p>
<p>NPC问题的定义非常简单 - <strong>if it is in NP and is as “hard” as any problem in NP</strong>。同时满足下面两个条件的问题就是NPC问题。<strong>首先，它得是一个NP问题；然后，所有的NP问题都可以约化到它。</strong>证明一个问题是 NPC问题也很简单。先证明它至少是一个NP问题，再证明其中一个已知的NPC问题能约化到它（由约化的传递性，则NPC问题定义的第二条也得以满足；至于第一个NPC问题是怎么来的，下文将介绍），这样就可以说它是NPC问题了。<br>         既然所有的NP问题都能约化成NPC问题，那么只要任意一个NPC问题找到了一个多项式的算法，那么所有的NP问题都能用这个算法解决了，NP也就等于P 了。因此，给NPC找一个多项式算法太不可思议了。因此，前文才说，“正是NPC问题的存在，使人们相信P≠NP”。我们可以就此直观地理解，NPC问题目前没有多项式的有效算法，只能用指数级甚至阶乘级复杂度的搜索。</p>
<p>​    <strong>如果能够判断出要解决的问题属于NP完全问题就好了，这样就不用去寻找完美的解决方案，而是使用近似算法即可。但要判断问题是不是NP完全问题很难，易于解决的问题和NP完全问题的差别通常很小。</strong></p>
<h3 id="NP-Hard问题"><a href="#NP-Hard问题" class="headerlink" title="NP-Hard问题"></a>NP-Hard问题</h3><p>​    顺便讲一下NP-Hard问题。NP-Hard问题是这样一种问题，它满足NPC问题定义的第二条但不一定要满足第一条（就是说，NP-Hard问题要比 NPC问题的范围广）。NP-Hard问题同样难以找到多项式的算法，但它不列入我们的研究范围，因为它不一定是NP问题。即使NPC问题发现了多项式级的算法，NP-Hard问题有可能仍然无法得到多项式级的算法。事实上，由于NP-Hard放宽了限定条件，它将有可能比所有的NPC问题的时间复杂度更高从而更难以解决。</p>
<p>​    有了第一个NPC问题后，一大堆NPC问题就出现了，因为再证明一个新的NPC问题只需要将一个已知的NPC问题约化到它就行了。后来，Hamilton 回路成了NPC问题，TSP问题也成了NPC问题。现在被证明是NPC问题的有很多，任何一个找到了多项式算法的话所有的NP问题都可以完美解决了。因此说，正是因为NPC问题的存在，P=NP变得难以置信。P=NP问题还有许多有趣的东西，有待大家自己进一步的挖掘。攀登这个信息学的巅峰是我们这一代的终极目标。现在我们需要做的，至少是不要把概念弄混淆了。</p>
<h3 id="总结"><a href="#总结" class="headerlink" title="总结"></a>总结</h3><ol>
<li><p>P Problem：这个应该最易理解，就是一个问题可以在Polynominal的时间的得到解决，当然，是对于任意input size。</p>
</li>
<li><p>NP Problem：对于一类问题，我们可能没有一个已知的快速的方法得到问题的答案，但是如果给我们一个candidate answer，我们能够在polynominal的时间内验证这个candidate answer到底是不是我们已知问题的答案，这类问题叫做NP problem。所以很显然 P Problem是NP problem的一个子集。</p>
</li>
<li><p>NP-hard Problem：对于这一类问题，用一句话概括他们的特征就是“at least as hard as the hardest problems in NP Problem”， 就是NP-hard问题至少和NPC问题一样难。</p>
</li>
<li><p>NP-Complete Problem：对于这一类问题，他们满足两个性质，一个就是在polynomial时间内可以验证一个candidate answer是不是真正的解，另一个性质就是我们可以把任何一个NP问题在polynomial的时间内把他的input转化，使之成为一个NP-complete问题（即规约）。NP-Complete Problem问题可以互相转换 (在多项式时间内)，只要其中一个问题可以在多项式时间内解决，那么其他问题也都将可以在多项式时间内解决。</p>
<img src="/2021/01/17/%E7%AE%97%E6%B3%95%E5%A4%8D%E6%9D%82%E5%BA%A6/image-20210116153241787@2x.png" class title="title text" alt="alt text">

<p>NP问题：首先，要理理解验证解的概念。给定一个问题，我们可能不知道如何解，但如果通过连蒙带猜，得到了了一个解。 我们也可以验证这个解是否满足问题。NP 就是指能在多项式时间内验证一个解是否满⾜的一类问题。 所以，P和NP并非补集关系，而是两个完全不同的分类⽅方式。</p>
</li>
<li><p>NPC问题：显然，所有P类问题都能在多项式时间内验证一个解。因此 P ⊆ NP。 于是人们就在想NP的问题里⾯，有最难的问题吗?它会是什么? 结论是，<strong>NP中有最难 的一类问题。这类问题就是 NP-Complete 问题。最难，就意味着所有NP类的问题都能归约到这个问题上。该问题本身也是NP问题。</strong><br>所以，NP-Complete问题的形式化定义是: L是NP-Complete问题，当其满足如下两个条件:<br>L ∈ NP<br>任意L1 ∈ NP, L1 可以归约到 L<br>对于只满⾜条件2,不管满不满足条件1的问题，我们称为NP-hard问题， 即非常难。</p>
</li>
<li><p>NP-hard<br>这⾥在说NP-hard，NP-hard实际上是“at least as hard as an NP-complete problem”,即这个问题⾄至少和NP完全问题⼀样难，所以不用满⾜上⾯的条件1.</p>
</li>
</ol>

      
    </div>

    
    
    
      <footer class="post-footer">
        <div class="post-eof"></div>
      </footer>
  </article>
  
  
  

      
  
  
  <article itemscope itemtype="http://schema.org/Article" class="post-block" lang="zh-CN">
    <link itemprop="mainEntityOfPage" href="http://example.com/2021/01/13/%E5%BE%AE%E6%9C%8D%E5%8A%A1%E6%9E%84%E6%9E%B6%E5%8F%8A%E7%8E%B0%E7%8A%B6%E5%88%86%E6%9E%90/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="image" content="/images/avatar.gif">
      <meta itemprop="name" content="greentree">
      <meta itemprop="description" content="">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="解救Z先生">
    </span>
      <header class="post-header">
        <h2 class="post-title" itemprop="name headline">
          
            <a href="/2021/01/13/%E5%BE%AE%E6%9C%8D%E5%8A%A1%E6%9E%84%E6%9E%B6%E5%8F%8A%E7%8E%B0%E7%8A%B6%E5%88%86%E6%9E%90/" class="post-title-link" itemprop="url">微服务构架及现状分析</a>
        </h2>

        <div class="post-meta">
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="far fa-calendar"></i>
              </span>
              <span class="post-meta-item-text">发表于</span>
              

              <time title="创建时间：2021-01-13 21:53:34 / 修改时间：22:24:40" itemprop="dateCreated datePublished" datetime="2021-01-13T21:53:34+08:00">2021-01-13</time>
            </span>

          

        </div>
      </header>

    
    
    
    <div class="post-body" itemprop="articleBody">

      
          <h3 id="什么是微服务框架"><a href="#什么是微服务框架" class="headerlink" title="什么是微服务框架"></a>什么是微服务框架</h3><p>微服务是系统构架上的一种设计风格，它的主旨是将一个原本独立的系统拆分成多个小型服务，这些小型服务在各自独立的进程中运行，服务之间通过基于HTTP的RESTful API进行通信协作。被拆分成的每一个小型服务都围绕着系统中的某一项或一些耦合度较高的业务功能进行构建，并且每个服务都维护着自身的数据存储、业务开发、自动化测试案例以及独立部署机制。由于有了轻量级的通信协作基础，所以这些微服务可以使用不同的语言来编写。</p>
<h3 id="微服务框架的优点"><a href="#微服务框架的优点" class="headerlink" title="微服务框架的优点"></a>微服务框架的优点</h3><ol>
<li>易于开发和维护，复杂度可控： 一个微服务只会关注一个特定的业务功能，所以它业务清晰、代码量少。开发和维护单个微服务相对简单。而整个应用是由若干个微服务构建而成的，所以整个应用也会被维持在一个可控状态。</li>
<li>局部修改容易，可独立部署某个微服务： 单体应用只要有修改，就得重新部署整个应用；一般来说，对某个微服务进行修改，只需要重新部署这个服务即可。</li>
<li>技术栈不受限，技术选型更灵活 ： 在微服务构架中，每个微服务都可由不同的团队来维护，所以结合项目业务及团队特点，自由地选择技术栈。</li>
<li>按需伸缩，可扩展性更强： 可根据每个微服务的性能需求和业务特点对服务进行优化和灵活扩展。例如，系统中的某个微服务遇到了瓶颈，可以结合这个微服务的业务特点，增加单个服务外的集群规模，提升部署了该服务节点的硬件配置等。</li>
</ol>
<h3 id="微服务构架面临的挑战"><a href="#微服务构架面临的挑战" class="headerlink" title="微服务构架面临的挑战"></a>微服务构架面临的挑战</h3><ol>
<li>故障排除：一次请求可能会经历多个不同的微服务的多次交互，交互的链路可能会比较长，每个微服务都会产生自己的日志，在这种情况下如果出现一个故障，开发人员定位问题的根源会比较困难。</li>
<li>运维成本： 更多的服务意味着更多的运维投入。在单体构架中，只需要保证一个应用的正常运行。而在微服务中，需要保证几十甚至几百个服务的正常运行与协作，如何快速部署和管理众多的服务成为挑战。</li>
<li>分布式构架的复杂性： 使用微服务构建的是分布式系统。对于一个分布式系统，系统容错、网络延迟、分布式事务等都会带来巨大的挑战。</li>
<li>服务依赖： 微服务数量增加之后，各个服务中之间会存在更多的依赖关系，使得系统整体更为复杂</li>
<li>服务监控：在微服务构架中，服务监控开销会非常大。不仅要对整个链路进行监控，还需要对每一个微服务都实现一套类似单体构架的监控。</li>
</ol>
<h3 id="微服务设计原则"><a href="#微服务设计原则" class="headerlink" title="微服务设计原则"></a>微服务设计原则</h3><ol>
<li>单一职责原则</li>
<li>服务自治原则：每个微服务应具备独立的业务能力、依赖和运行环境。在微服务构架中，服务是独立的业务单元，应该与其它服务高度解耦。每个微服务从开发、测试、构建、部署，都应当可以独立运行，而不应该依赖其它的服务</li>
<li>轻量级通信机制： 体量轻；跨语言、跨平台的。微服务框架中，常用的协议有REST、AMQP、STOMP、MQTT（Message Queuing Telemetry Transport,消息队列遥测传输协议)。</li>
<li>微服务粒度：康威定律（ <a target="_blank" rel="noopener" href="https://www.cnblogs.com/still-smile/p/11646609.html%EF%BC%89">https://www.cnblogs.com/still-smile/p/11646609.html）</a></li>
</ol>
<h3 id="微服务实现构架-Spring-Cloud"><a href="#微服务实现构架-Spring-Cloud" class="headerlink" title="微服务实现构架 - Spring Cloud"></a>微服务实现构架 - Spring Cloud</h3><p>尽管微服务构架为复杂业务提供了很好的解决方案，但是也给开发、测试、运维带来了非常大的挑战。在微服务一体化解决方案出现之前，各个公司在实现微服务化的过程中都比较痛苦，直到Spring Cloud的出现。</p>
<p>目前Spring Cloud是作为微服务开发框架的最佳选择。Spring Cloud是Pivotal公司在2015年发布的一个项目，Spring就是Pivotal公司研发的。Spring Cloud为微服务构架提供了完整的解决方案，它提供了可以让开发者快速构建微服务应用的工具，比如配置管理、服务发现、熔断、智能路由等。这些服务可以在任何分布式环境下很好地工作，其核心功能包括</p>
<ul>
<li>Distributed/versioned configuration 分布式/版本化的配置管理</li>
<li>Service registration and discovery 服务注册与服务发现</li>
<li>Routing 路由</li>
<li>Service-to-service calls 端到端的调用</li>
<li>Load balancing 负载均衡</li>
<li>Circuit Breakers 断路器</li>
<li>Global locks 全局锁</li>
<li>Leadership election and cluster state 选举与集群状态管理</li>
<li>Distributed messaging 分布式消息</li>
</ul>
<p>Spring Cloud并不是Spring团队全新研发的框架，它只是把一些比较优秀的解决微服务框架中常见问题的开源框架基于Spring Colud规范进行了整合，<strong>通过Spring Boot这个框架进行再次封装</strong>后屏蔽掉了复杂的配置，给开发者提供良好的微服务开发体验。尽管Spring Cloud带有“Cloud”的字样，但它并不是云计算解决方案，而<strong>是在Spring Boot基础上构建的，用于快速构建分布式系统的通用模式的工具集</strong>。不难看出，Spring Cloud就是一套整合了各大公司开源技术的规范，而Spring Cloud Neteflix、Spring Cloud Consul、Spring Cloud Alibaba才是Spring Cloud规范的实现。</p>
<p>Spring Cloud非常适合在我们目前的团队中使用。首先，Spring Cloud具备开箱即用的生产特性，可大大提升开发效率；其次，Spring Cloud的文档丰富、社区活跃，遇到问题比较容易获得支持。最后，使用Spring Cloud开发的应用程序非常适合在Docker或者PaaS（例如Cloud Foundry）上部署，所以又叫做云原生应用（Cloud Native Application）。云原生（Cloud Native）可简单理解为面向云环境的软件架构。微服务并不绑定运行平台，将微服务部署在PC Server，或者阿里云、AWS等云计算平台都是可以的。可以方便的通过Docker/Podman/K8s进行微服务部署。</p>
<p>Spring Cloud规范下的实现 - 在Spring Cloud这个规范下，有很多实现，比如：</p>
<ol>
<li>Spring-Cloud-Bus</li>
<li>Spring-Cloud-Netflix</li>
<li>Spring-Cloud-Zookeeper</li>
<li>Spring-Cloud-Gateway</li>
</ol>
<p>在这些实现中，绝大部分组件都使用“别人已经造好的轮子”，然后基于Spring Cloud规范进行整合，使用者只需要使用非常简单的配置即可完成微服务框架下复杂的需求。只有在别人提供的东西不够好的情况下，Spring团队才会考虑自己研发。比如Spring Cloud Netlflix中的Zuul网关，因为性能及版本迭代较慢，所以孵化了一个Spring Cloud Gateway来取代Zuul。</p>
<p>Spring Cloud生态下服务治理的解决方案主要有两个：Spring Cloud Netflix和Spring Cloud Alibaba。这两个解决方案分别针对Netflix OSS及Alibaba的服务治理体系基于Spring Cloud规范做的整合。</p>
<h3 id="Spring-Cloud生态下服务治理解决方案-Spring-Could-Netflix-vs-Spring-Cloud-Alibaba"><a href="#Spring-Cloud生态下服务治理解决方案-Spring-Could-Netflix-vs-Spring-Cloud-Alibaba" class="headerlink" title="Spring Cloud生态下服务治理解决方案 - Spring Could Netflix vs. Spring Cloud Alibaba"></a>Spring Cloud生态下服务治理解决方案 - Spring Could Netflix vs. Spring Cloud Alibaba</h3><p>从2016年开始，Spring Cloud逐步在国内普及，它提供了微服务开发、服务治理、监控等一体化解决方案。有了这个生态，中小型互联网公司要构建微服务，不需要再去找各种开源组件来集成。通过Spring Cloud可以轻松快速地构建微服务。</p>
<p>Spring Cloud服务治理的整个体系采用的是Netflix公司提供的开源组件，但是Netflix公司开源组件的活跃度不是很高，并且Netflix公司官方也声明了对于很多组件逐步进入维护模式。所以Spring Cloud官方发布了声明，Spring Cloud Netflix下的相关组件也会逐步进入维护模式（进入维护模式的意思就是从目前一直到以后一段时间Spring Cloud Netflix提供的服务和功能就这么多了，不再开发新的组件和功能了）。同时Spring Cloud 官方也在积极孵化其他替代品，以满足Spring Cloud 版本迭代的需求。</p>
<p>值得高兴的是，2018年10月31日的凌晨，Spring Cloud Alibaba正式入驻Spring Cloud官方孵化器，并在Maven中央库发布了第一个版本；2019年8月1日，在Alibaba仓库发布了第一个毕业版本。</p>
<p>Spring Cloud Alibaba生态下的各个组件其实在国内很多公司很早之前就有使用，它们在服务治理方面比Spring Cloud Netflix更加强大，而且比较符合国内互联网公司的业务特性！</p>
<p>Spring CloudNetflix 主要为微服务框架下的服务治理提供解决方案，包括以下组件：</p>
<ol>
<li>Eureka - 服务注册与发现</li>
<li>Zuul - 服务网关</li>
<li>Ribbon - 负载均衡</li>
<li>Feign - 远程服务的客户端代理</li>
<li>Hystrix - 断路器，提供服务熔断和限流功能</li>
<li>Hystrix Dashboard - 监控面板</li>
<li>Turbine - 将各个服务实例上的Hystrix监控信息进行统一聚合</li>
</ol>
<p>Spring Cloud Alibaba主要为微服务开发提供一站式的解决方案，使开发者通过Spring Cloud编程模型轻松地解决微服务框架下的各类技术问题。以下是Spring Cloud Alibaba生态下的主要功能组件：</p>
<ol>
<li>Sentinel - 流量控制和服务降级</li>
<li>Nacos - 服务注册与发现</li>
<li>Nacos - 分布式配置中心</li>
<li>RocketMQ - 消息驱动</li>
<li>Seate - 分布式事务</li>
<li>Dubbo - RPC通信</li>
<li>OSS - 阿里云对象存储（收费的云服务）</li>
</ol>
<h2 id="Spring-Cloud-Netflix"><a href="#Spring-Cloud-Netflix" class="headerlink" title="Spring Cloud Netflix"></a><strong>Spring Cloud Netflix</strong></h2><p>目前业界对Spring Cloud使用最广的就是Spring Cloud Netflix了。这TM一下80%都进入“维护模式”，再也没有新功能福利了，让人如何是好啊！<strong>就目前来看，继续使用Spring Cloud Netflix问题不大，但长期来看，显然是不合适的。</strong></p>
<p>官方建议的替代项目如下表所示：</p>
<table>
<thead>
<tr>
<th align="left">当前</th>
<th align="left">替代项目</th>
</tr>
</thead>
<tbody><tr>
<td align="left">Hystrix</td>
<td align="left"><a target="_blank" rel="noopener" href="https://github.com/resilience4j/resilience4j">Resilience4j</a></td>
</tr>
<tr>
<td align="left">Hystrix Dashboard / Turbine</td>
<td align="left">Micrometer + Monitoring System</td>
</tr>
<tr>
<td align="left">Ribbon</td>
<td align="left">Spring Cloud Loadbalancer</td>
</tr>
<tr>
<td align="left">Zuul 1</td>
<td align="left">Spring Cloud Gateway</td>
</tr>
<tr>
<td align="left">Archaius 1</td>
<td align="left">Spring Boot external config + Spring Cloud Config</td>
</tr>
</tbody></table>
<h2 id="未来-amp-其他的候选者"><a href="#未来-amp-其他的候选者" class="headerlink" title="未来&amp;其他的候选者"></a>未来&amp;其他的候选者</h2><p>我相信未来Spring Cloud的生态会越来越好。事实上Spring Cloud生态中还有其他的替换项目&amp;更多选择：</p>
<table>
<thead>
<tr>
<th align="left">作用</th>
<th align="left">业界用得最多</th>
<th align="left">已孵化成功的替代项目</th>
<th align="left">孵化中的替代项目</th>
</tr>
</thead>
<tbody><tr>
<td align="left">服务发现</td>
<td align="left">Eureka</td>
<td align="left">Consul、Zookeeper</td>
<td align="left">Alibaba Nacos</td>
</tr>
<tr>
<td align="left">负载均衡器</td>
<td align="left">Ribbon</td>
<td align="left">-</td>
<td align="left">-（Hoxton M3才会有替代品）</td>
</tr>
<tr>
<td align="left">断路器</td>
<td align="left">Hystrix</td>
<td align="left">-</td>
<td align="left">Resilience4j、Alibaba Sentinel</td>
</tr>
<tr>
<td align="left">声明式HTTP客户端</td>
<td align="left">Feign</td>
<td align="left">-</td>
<td align="left">Retrofit</td>
</tr>
<tr>
<td align="left">API网关</td>
<td align="left">Zuul 1</td>
<td align="left">Spring Cloud Gateway</td>
<td align="left">-</td>
</tr>
<tr>
<td align="left">配置管理</td>
<td align="left">Spring Cloud Config</td>
<td align="left">Consul、Zookeeper</td>
<td align="left">Alibaba Nacos</td>
</tr>
</tbody></table>
<h3 id="补充信息-Alibaba-Nacos"><a href="#补充信息-Alibaba-Nacos" class="headerlink" title="补充信息 - Alibaba Nacos"></a>补充信息 - Alibaba Nacos</h3><p>Nacos 是阿里开源的易于构建云原生应用的动态服务发现、配置管理和服务管理平台。</p>
<p>Nacos 致力于帮助您发现、配置和管理微服务。Nacos 提供了一组简单易用的特性集，帮助您快速实现动态服务发现、服务配置、服务元数据及流量管理。</p>
<p><strong>通俗来说，Nacos是一个注册中心&amp; 配置中心</strong> ——作为注册中心，Nacos可用于替代Spring Cloud中的Eureka、Spring Cloud Zookeeper Discovery、Spring Cloud Consul Discovery；作为配置中心，Nacos可用于替代Spring Cloud Config、Spring Cloud Zookeper Config、Spring Cloud Consul Config。</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">TIPS：</span><br><span class="line">其实从Nacos命名的由来：Dynamic Naming and Configuration Service 即可顾名思义了。</span><br></pre></td></tr></table></figure>
<p>Nacos - 它使用内嵌数据库Derby，这显然不适用于生产</p>
<p>Nacos -  配置管理，不用GIT server方案，也不用Spring Cloud Bus + AMQP方案通知各个微服务</p>
<img src="/2021/01/13/%E5%BE%AE%E6%9C%8D%E5%8A%A1%E6%9E%84%E6%9E%B6%E5%8F%8A%E7%8E%B0%E7%8A%B6%E5%88%86%E6%9E%90/hero-image@2x.png" class title="title text" alt="alt text">

<p>Nacos -  高可用集群方案，可以使用Nginx后跟多个Nacos服务器，每个服务器连接高可靠的数据库服务器；这点和Eureka的高可用方案不同；<a target="_blank" rel="noopener" href="http://www.itmuch.com/spring-cloud-alibaba/nacos-ha/">http://www.itmuch.com/spring-cloud-alibaba/nacos-ha/</a></p>
<h3 id="补充信息-Eureka-高可用"><a href="#补充信息-Eureka-高可用" class="headerlink" title="补充信息 - Eureka 高可用"></a><strong>补充信息 - Eureka 高可用</strong></h3><p>通过部署多节点 Eureka 实例，避免单点问题，满足高可用架构。同时节点之间的地位是平等，节点通信方式采用点对点方式（peer to peer），以便满足数据同步问题，这是一种去中心化的分布式架构。在这种架构中，peer 节点之间通过相互注册来提高可用性，每个peer节点通过serviceUrl指定其他peer节点。如果某台Eureka服务器宕机，Eureka客户端的请求会自动切换到新的Eureka服务器节点，当宕机的服务器重新恢复后，Eureka会再次将其纳入到服务器集群管理中。当节点开始接受客户端请求时，所有的操作也会进行节点间复制，将请求复制到其他Eureka服务器当前所知的节点中。</p>
<h2 id="补充信息-Alibaba-Sentinel"><a href="#补充信息-Alibaba-Sentinel" class="headerlink" title="补充信息 - Alibaba Sentinel"></a>补充信息 - Alibaba Sentinel</h2><p>随着微服务的流行，服务和服务之间的稳定性变得越来越重要。Sentinel 以流量为切入点，从流量控制、熔断降级、系统负载保护等多个维度保护服务的稳定性。</p>
<p>简单来说，<strong>Sentinel是一个轻量级的流量控制、熔断降级 Java 库。</strong></p>
<p>Sentinel 具有以下特征:</p>
<ul>
<li><p><strong>丰富的应用场景</strong>：Sentinel 承接了阿里巴巴近 10 年的双十一大促流量的核心场景，例如秒杀（即突发流量控制在系统容量可以承受的范围）、消息削峰填谷、集群流量控制、实时熔断下游不可用应用等。</p>
</li>
<li><p><strong>完备的实时监控</strong>：Sentinel 同时提供实时的监控功能。您可以在控制台中看到接入应用的单台机器秒级数据，甚至 500 台以下规模的集群的汇总运行情况。</p>
</li>
<li><p><strong>广泛的开源生态</strong>：Sentinel 提供开箱即用的与其它开源框架/库的整合模块，例如与 Spring Cloud、Dubbo、gRPC 的整合。您只需要引入相应的依赖并进行简单的配置即可快速地接入 Sentinel。</p>
</li>
<li><p><strong>完善的 SPI 扩展点</strong>：Sentinel 提供简单易用、完善的 SPI 扩展接口。您可以通过实现扩展接口来快速地定制逻辑。例如定制规则管理、适配动态数据源等。</p>
</li>
</ul>
<h3 id="参考资料"><a href="#参考资料" class="headerlink" title="参考资料"></a>参考资料</h3><ol>
<li><p>Spring Cloud系列教程</p>
<p><a target="_blank" rel="noopener" href="http://www.itmuch.com/spring-cloud/spring-cloud-index/">http://www.itmuch.com/spring-cloud/spring-cloud-index/</a></p>
</li>
<li><p>高可用MySQL的搭建可参考</p>
<p><a target="_blank" rel="noopener" href="https://blog.csdn.net/jx_jy/article/details/80165584">https://blog.csdn.net/jx_jy/article/details/80165584</a></p>
<p><a target="_blank" rel="noopener" href="https://imysql.com/2015/09/14/solutions-of-mysql-ha.shtml">https://imysql.com/2015/09/14/solutions-of-mysql-ha.shtml</a></p>
</li>
<li><p>Spring Cloud - Nacos与Eureka区别及如何选型</p>
<p><a target="_blank" rel="noopener" href="https://perkins4j2.github.io/posts/35353/">https://perkins4j2.github.io/posts/35353/</a></p>
</li>
<li><p><strong>2018/12/12 - The following Spring Cloud Netflix modules and corresponding starters will be placed into maintenance mode</strong>:</p>
<p>spring-cloud-netflix-archaius<br>spring-cloud-netflix-hystrix-contract<br>spring-cloud-netflix-hystrix-dashboard<br>spring-cloud-netflix-hystrix-stream<br>spring-cloud-netflix-hystrix<br>spring-cloud-netflix-ribbon<br>spring-cloud-netflix-turbine-stream<br>spring-cloud-netflix-turbine<br>spring-cloud-netflix-zuul<br>This does not include the Eureka or concurrency-limits modules.</p>
<p><strong>What is Maintenance Mode</strong>?<br>Placing a module in maintenance mode means that the Spring Cloud team will no longer be adding new features to the module. We will fix blocker bugs and security issues, and we will also consider and review small pull requests from the community.</p>
<p><a target="_blank" rel="noopener" href="https://spring.io/blog/2018/12/12/spring-cloud-greenwich-rc1-available-now#spring-cloud-netflix-projects-entering-maintenance-mode">https://spring.io/blog/2018/12/12/spring-cloud-greenwich-rc1-available-now#spring-cloud-netflix-projects-entering-maintenance-mode</a></p>
</li>
</ol>

      
    </div>

    
    
    
      <footer class="post-footer">
        <div class="post-eof"></div>
      </footer>
  </article>
  
  
  

      
  
  
  <article itemscope itemtype="http://schema.org/Article" class="post-block" lang="zh-CN">
    <link itemprop="mainEntityOfPage" href="http://example.com/2021/01/12/jdk11%E7%9A%84jni%E7%BC%96%E7%A8%8B/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="image" content="/images/avatar.gif">
      <meta itemprop="name" content="greentree">
      <meta itemprop="description" content="">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="解救Z先生">
    </span>
      <header class="post-header">
        <h2 class="post-title" itemprop="name headline">
          
            <a href="/2021/01/12/jdk11%E7%9A%84jni%E7%BC%96%E7%A8%8B/" class="post-title-link" itemprop="url">jdk11的jni编程</a>
        </h2>

        <div class="post-meta">
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="far fa-calendar"></i>
              </span>
              <span class="post-meta-item-text">发表于</span>

              <time title="创建时间：2021-01-12 22:31:38" itemprop="dateCreated datePublished" datetime="2021-01-12T22:31:38+08:00">2021-01-12</time>
            </span>
              <span class="post-meta-item">
                <span class="post-meta-item-icon">
                  <i class="far fa-calendar-check"></i>
                </span>
                <span class="post-meta-item-text">更新于</span>
                <time title="修改时间：2021-01-13 21:47:59" itemprop="dateModified" datetime="2021-01-13T21:47:59+08:00">2021-01-13</time>
              </span>

          

        </div>
      </header>

    
    
    
    <div class="post-body" itemprop="articleBody">

      
          <h1 id="jdk11的jni编程"><a href="#jdk11的jni编程" class="headerlink" title="jdk11的jni编程"></a>jdk11的jni编程</h1><p>首先写一个测试Class   </p>
<pre><code>public class JNIDemo &#123;
    //定义一个方法，该方法在C中实现
    public native void testHello();
    public static void main(String[] args)&#123;
        //加载C文件
        System.loadLibrary(&quot;JNIDemo&quot;);//C的动态链接库的名字
        System.out.println(&quot;加载成功&quot;);
        JNIDemo jniDemo = new JNIDemo();//本测试类
        jniDemo.testHello();
    &#125;
&#125;    </code></pre>
<p>接下来就是生成头文件了</p>
<p>执行命令<br>**</p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">javac -h jni JNIDemo.java</span><br></pre></td></tr></table></figure>
<p>jni是文件存放目录，JNIDemo.java是测试类<br>**</p>
<p>头文件里面的内容</p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/* DO NOT EDIT THIS FILE - it is machine generated */</span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;jni.h&gt;</span></span></span><br><span class="line"><span class="comment">/* Header for class JNIDemo */</span></span><br><span class="line"></span><br><span class="line"><span class="meta">#<span class="meta-keyword">ifndef</span> _Included_JNIDemo</span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">define</span> _Included_JNIDemo</span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">ifdef</span> __cplusplus</span></span><br><span class="line"><span class="keyword">extern</span> <span class="string">&quot;C&quot;</span> &#123;</span><br><span class="line"><span class="meta">#<span class="meta-keyword">endif</span></span></span><br><span class="line"><span class="comment">/*</span></span><br><span class="line"><span class="comment"></span></span><br><span class="line"><span class="comment"> * Class:     JNIDemo</span></span><br><span class="line"><span class="comment"> * Method:    testHello</span></span><br><span class="line"><span class="comment"> * Signature: ()V</span></span><br><span class="line"><span class="comment">   */</span></span><br><span class="line">   JNIEXPORT <span class="keyword">void</span> JNICALL Java_JNIDemo_testHello</span><br><span class="line">   (JNIEnv *, jobject);</span><br><span class="line"></span><br><span class="line"><span class="meta">#<span class="meta-keyword">ifdef</span> __cplusplus</span></span><br><span class="line">&#125;</span><br><span class="line"><span class="meta">#<span class="meta-keyword">endif</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">endif</span></span></span><br></pre></td></tr></table></figure>
<p>那么我们就实现这个C的函数</p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&quot;JNIDemo.h&quot;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;string.h&gt;</span></span></span><br><span class="line"></span><br><span class="line">JNIEXPORT <span class="keyword">void</span> JNICALL Java_JNIDemo_testHello</span><br><span class="line">  (JNIEnv *env, jobject obj)</span><br><span class="line">&#123;</span><br><span class="line">    <span class="built_in">printf</span>(<span class="string">&quot;Hello Jni\n&quot;</span>);</span><br><span class="line">    <span class="keyword">return</span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&quot;JNIDemo.h&quot;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;string.h&gt;</span></span></span><br><span class="line"></span><br><span class="line">JNIEXPORT <span class="keyword">void</span> JNICALL Java_JNIDemo_testHello</span><br><span class="line">  (JNIEnv *env, jobject obj)</span><br><span class="line">&#123;</span><br><span class="line">    <span class="built_in">printf</span>(<span class="string">&quot;Hello Jni\n&quot;</span>);</span><br><span class="line">    <span class="keyword">return</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>接着编译并生成O文件</p>
<p>**<br>/usr/lib/jvm/java-11-oracle/include  这个是JDK路径<br>./jni/JNIDemo.c 这个是我们刚刚写的C文件路径</p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">gcc -c -fPIC -I /usr/lib/jvm/java-11-oracle/include -I /usr/lib/jvm/java-11-oracle/include/linux ./jni/JNIDemo.c -o JNIDemo.o</span><br></pre></td></tr></table></figure>
<p>JDK路径可以用${JAVA_HOME}代替</p>
<p>**</p>
<p>我们还要生成SO文件<br>**</p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">gcc -shared JNIDemo.o -o libJNIDemo.so</span><br></pre></td></tr></table></figure>
<p>**</p>
<p>通知动态链接程序此共享文件的路径<br>export LD_LIBRARY_PATH=pwd:$LD_LIBRARY_PATH</p>
<p>也可以把so文件复制到/usr/lib目录下</p>
<p>接着就可以正常编译java，并运行了。</p>

      
    </div>

    
    
    
      <footer class="post-footer">
        <div class="post-eof"></div>
      </footer>
  </article>
  
  
  

      
  
  
  <article itemscope itemtype="http://schema.org/Article" class="post-block" lang="zh-CN">
    <link itemprop="mainEntityOfPage" href="http://example.com/2021/01/10/CSDN%E6%B2%A1%E6%9C%89%E7%A7%AF%E5%88%86%E6%80%8E%E4%B9%88%E5%85%8D%E8%B4%B9%E4%B8%8B%E8%BD%BD/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="image" content="/images/avatar.gif">
      <meta itemprop="name" content="greentree">
      <meta itemprop="description" content="">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="解救Z先生">
    </span>
      <header class="post-header">
        <h2 class="post-title" itemprop="name headline">
          
            <a href="/2021/01/10/CSDN%E6%B2%A1%E6%9C%89%E7%A7%AF%E5%88%86%E6%80%8E%E4%B9%88%E5%85%8D%E8%B4%B9%E4%B8%8B%E8%BD%BD/" class="post-title-link" itemprop="url">CSDN没有积分怎么免费下载</a>
        </h2>

        <div class="post-meta">
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="far fa-calendar"></i>
              </span>
              <span class="post-meta-item-text">发表于</span>
              

              <time title="创建时间：2021-01-10 22:08:17 / 修改时间：22:10:23" itemprop="dateCreated datePublished" datetime="2021-01-10T22:08:17+08:00">2021-01-10</time>
            </span>

          

        </div>
      </header>

    
    
    
    <div class="post-body" itemprop="articleBody">

      
          <h2 id="CSDN没有积分怎么免费下载？"><a href="#CSDN没有积分怎么免费下载？" class="headerlink" title="CSDN没有积分怎么免费下载？"></a>CSDN没有积分怎么免费下载？</h2><h3 id="最迂回的方法——找替代网站"><a href="#最迂回的方法——找替代网站" class="headerlink" title="最迂回的方法——找替代网站"></a>最迂回的方法——找替代网站</h3><p>要知道获取资源的网站并不只有CSDN，可以找相关的替代网站。可以把名字放到一些盘搜网站去搜索，或者用关键词filetype:pdf放到谷歌、百度上搜。</p>
<p>推荐的一些网站可以用来搜电子书、文档和软件：</p>
<p>云盘精灵</p>
<p><a target="_blank" rel="noopener" href="https://www.yunpanjingling.com/">https://www.yunpanjingling.com/</a></p>
<p>ncckl</p>
<p><a target="_blank" rel="noopener" href="http://so.ncckl.cn/">http://so.ncckl.cn/</a></p>
<p>西林街</p>
<p><a target="_blank" rel="noopener" href="http://www.xilinjie.com/">http://www.xilinjie.com/</a></p>
<p>虫部落</p>
<p><a target="_blank" rel="noopener" href="http://www.chongbuluo.com/">http://www.chongbuluo.com/</a></p>
<p>计算机书籍控</p>
<p><a target="_blank" rel="noopener" href="http://bestcbooks.com/B00AK7BYJY/">http://bestcbooks.com/B00AK7BYJY/</a></p>
<p>Library Genesis</p>
<p><a target="_blank" rel="noopener" href="http://gen.lib.rus.ec/">http://gen.lib.rus.ec/</a></p>
<p>搜代码、技术文档类：</p>
<p>Github</p>
<p><a target="_blank" rel="noopener" href="https://github.com/">https://github.com/</a></p>
<p>searchcode</p>
<p><a target="_blank" rel="noopener" href="https://searchcode.com/">https://searchcode.com/</a></p>
<p>最代码</p>
<p><a target="_blank" rel="noopener" href="http://www.zuidaima.com/">http://www.zuidaima.com/</a></p>
<p>掘金</p>
<p><a target="_blank" rel="noopener" href="https://juejin.im/timeline">https://juejin.im/timeline</a></p>
<p>SegmentFault</p>
<p><a target="_blank" rel="noopener" href="https://segmentfault.com/">https://segmentfault.com/</a></p>
<h3 id="最快捷的方法——找代下"><a href="#最快捷的方法——找代下" class="headerlink" title="最快捷的方法——找代下"></a>最快捷的方法——找代下</h3><p>免费的方法：可以找一些公众号代下（因为公众号需要涨粉，所以一般也都是免费代下）</p>
<p>比如：懂你小站、资源库爱分享等公众号，直接发送CSDN的链接就好。</p>
<p>付费的方法：可以去淘宝搜CSDN代下、CSDN积分；可以去百度知道悬赏财富值代下；吾爱论坛悬赏CB代下。</p>

      
    </div>

    
    
    
      <footer class="post-footer">
        <div class="post-eof"></div>
      </footer>
  </article>
  
  
  

      
  
  
  <article itemscope itemtype="http://schema.org/Article" class="post-block" lang="zh-CN">
    <link itemprop="mainEntityOfPage" href="http://example.com/2021/01/10/Hexo%E6%9C%80%E5%B8%B8%E7%94%A8%E7%9A%84%E5%87%A0%E4%B8%AA%E5%91%BD%E4%BB%A4/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="image" content="/images/avatar.gif">
      <meta itemprop="name" content="greentree">
      <meta itemprop="description" content="">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="解救Z先生">
    </span>
      <header class="post-header">
        <h2 class="post-title" itemprop="name headline">
          
            <a href="/2021/01/10/Hexo%E6%9C%80%E5%B8%B8%E7%94%A8%E7%9A%84%E5%87%A0%E4%B8%AA%E5%91%BD%E4%BB%A4/" class="post-title-link" itemprop="url">Hexo最常用的几个命令</a>
        </h2>

        <div class="post-meta">
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="far fa-calendar"></i>
              </span>
              <span class="post-meta-item-text">发表于</span>

              <time title="创建时间：2021-01-10 10:10:03" itemprop="dateCreated datePublished" datetime="2021-01-10T10:10:03+08:00">2021-01-10</time>
            </span>
              <span class="post-meta-item">
                <span class="post-meta-item-icon">
                  <i class="far fa-calendar-check"></i>
                </span>
                <span class="post-meta-item-text">更新于</span>
                <time title="修改时间：2021-01-13 21:59:11" itemprop="dateModified" datetime="2021-01-13T21:59:11+08:00">2021-01-13</time>
              </span>

          

        </div>
      </header>

    
    
    
    <div class="post-body" itemprop="articleBody">

      
          <h1 id="Hexo最常用的几个命令"><a href="#Hexo最常用的几个命令" class="headerlink" title="Hexo最常用的几个命令"></a>Hexo最常用的几个命令</h1><blockquote>
<p>Hexo 约有二十个命令，但普通用户经常使用的大概只有下列几个:</p>
</blockquote>
<h2 id="hexo-s"><a href="#hexo-s" class="headerlink" title="hexo s"></a>hexo s</h2><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">hexo s</span><br></pre></td></tr></table></figure>
<p>启动本地服务器，用于预览主题。默认地址： <a target="_blank" rel="noopener" href="https://link.jianshu.com/?t=http://localhost:4000/">http://localhost:4000/</a></p>
<ul>
<li><code>hexo s</code> 是 <code>hexo server</code> 的缩写，命令效果一致；</li>
<li>预览的同时可以修改文章内容或主题代码，保存后刷新页面即可；</li>
<li>对 Hexo 根目录 <code>_config.yml</code> 的修改，需要重启本地服务器后才能预览效果。</li>
</ul>
<h2 id="hexo-n"><a href="#hexo-n" class="headerlink" title="hexo n"></a>hexo n</h2><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">hexo n <span class="string">&quot;学习笔记  六&quot;</span></span><br></pre></td></tr></table></figure>
<p>新建一篇标题为 <code>学习笔记 六</code> 的文章，因为标题里有空格，所以加上了引号。</p>
<ul>
<li>文章标题可以在对应 md 文件里改，新建时标题可以写的简单些；</li>
<li><code>hexo n</code> 是 <code>hexo new</code> 的缩写，命令效果一致。</li>
</ul>
<h3 id="文章可以拥有如下属性："><a href="#文章可以拥有如下属性：" class="headerlink" title="文章可以拥有如下属性："></a>文章可以拥有如下属性：</h3><table>
<thead>
<tr>
<th align="center">-</th>
<th>Setting</th>
<th>Description</th>
<th>Default</th>
</tr>
</thead>
<tbody><tr>
<td align="center">1</td>
<td>layout</td>
<td>Layout</td>
<td>post或page</td>
</tr>
<tr>
<td align="center">2</td>
<td>title</td>
<td>文章的标题</td>
<td></td>
</tr>
<tr>
<td align="center">3</td>
<td>date</td>
<td>创建日期</td>
<td>文件的创建日期</td>
</tr>
<tr>
<td align="center">4</td>
<td>updated</td>
<td>修改日期</td>
<td>文件的修改日期</td>
</tr>
<tr>
<td align="center">5</td>
<td>comments</td>
<td>是否开启评论</td>
<td>true</td>
</tr>
<tr>
<td align="center">6</td>
<td>tags</td>
<td>标签</td>
<td></td>
</tr>
<tr>
<td align="center">7</td>
<td>categories</td>
<td>分类</td>
<td></td>
</tr>
<tr>
<td align="center">8</td>
<td>permalink</td>
<td>url中的名字</td>
<td>文件名</td>
</tr>
</tbody></table>
<p>动态博客中通过发布文章页面设置的各种属性，在hexo里要这样设置。</p>
<h2 id="hexo-d"><a href="#hexo-d" class="headerlink" title="hexo d"></a>hexo d</h2><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">hexo d</span><br></pre></td></tr></table></figure>
<p>自动生成网站静态文件，并部署到设定的仓库。</p>
<ul>
<li><code>hexo d</code> 是 <code>hexo deploy</code> 的缩写，命令效果一致。</li>
</ul>
<h2 id="hexo-clean"><a href="#hexo-clean" class="headerlink" title="hexo clean"></a>hexo clean</h2><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">hexo clean</span><br></pre></td></tr></table></figure>
<p>清除缓存文件 <code>db.json</code> 和已生成的静态文件 <code>public</code>。</p>
<ul>
<li>网站显示异常时可以执行这条命令试试。</li>
</ul>
<h2 id="hexo-g"><a href="#hexo-g" class="headerlink" title="hexo g"></a>hexo g</h2><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">hexo g</span><br></pre></td></tr></table></figure>
<p>生成网站静态文件到默认设置的 <code>public</code> 文件夹。</p>
<ul>
<li>便于查看网站生成的静态文件或者手动部署网站；</li>
<li>如果使用自动部署，不需要先执行该命令；</li>
<li><code>hexo g</code> 是 <code>hexo generate</code> 的缩写，命令效果一致。</li>
</ul>
<h2 id="hexo-n-page"><a href="#hexo-n-page" class="headerlink" title="hexo n page"></a>hexo n page</h2><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">hexo n page aboutme</span><br></pre></td></tr></table></figure>
<p>新建一个标题为 <code>aboutme</code> 的页面，默认链接地址为 <code>主页地址/aboutme/</code></p>
<ul>
<li>标题可以为中文，但一般习惯用英文；</li>
<li>页面标题和文章一样可以随意修改；</li>
<li>页面不会出现在首页文章列表和归档中，也不支持设置分类和标签。</li>
</ul>
<h2 id="常用组合"><a href="#常用组合" class="headerlink" title="常用组合"></a>常用组合</h2><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">hexo clean &amp;&amp; hexo s</span><br><span class="line">hexo clean &amp;&amp; hexo d</span><br></pre></td></tr></table></figure>
<p>可以用输入法等软件为这些命令设置快捷键，方便调用。</p>
<h2 id="草稿"><a href="#草稿" class="headerlink" title="草稿"></a>草稿</h2><p>草稿相当于很多博客都有的“私密文章”功能。</p>
<figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">$ hexo <span class="keyword">new</span> draft <span class="string">&quot;new draft&quot;</span></span><br></pre></td></tr></table></figure>
<p>会在source/_drafts目录下生成一个new-draft.md文件。但是这个文件不被显示在页面上，链接也访问不到。也就是说如果你想把某一篇文章移除显示，又不舍得删除，可以把它移动到_drafts目录之中。</p>
<ul>
<li>如果你希望强行预览草稿，更改配置文件：</li>
</ul>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">render_drafts: <span class="literal">true</span></span><br></pre></td></tr></table></figure>
<ul>
<li>或者，如下方式启动server：</li>
</ul>
<figure class="highlight ruby"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="variable">$ </span>hexo server --drafts</span><br></pre></td></tr></table></figure>
<ul>
<li>下面这条命令可以把草稿变成文章，或者页面：</li>
</ul>
<figure class="highlight ruby"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="variable">$ </span>hexo publish [layout] &lt;filename&gt;</span><br></pre></td></tr></table></figure>
<h2 id="相关说明"><a href="#相关说明" class="headerlink" title="相关说明"></a>相关说明</h2><ul>
<li>以上命令使用基于 Hexo 3.1.1 版本；</li>
<li>需要删掉用命令新建的文章或页面时，只需要进入 Hexo 根目录下的 <code>source</code> 文件夹，删除对应文件或文件夹即可；</li>
<li>更多命令用法请查询 <a target="_blank" rel="noopener" href="https://link.jianshu.com/?t=https://hexo.io/zh-cn/docs/commands.html">官方文档</a>。</li>
</ul>
<p>作者：指尖的跳跃<br>链接：<a target="_blank" rel="noopener" href="https://www.jianshu.com/p/a2d298e26dcd">https://www.jianshu.com/p/a2d298e26dcd</a><br>来源：简书<br>著作权归作者所有。商业转载请联系作者获得授权，非商业转载请注明出处。</p>

      
    </div>

    
    
    
      <footer class="post-footer">
        <div class="post-eof"></div>
      </footer>
  </article>
  
  
  

      
  
  
  <article itemscope itemtype="http://schema.org/Article" class="post-block" lang="zh-CN">
    <link itemprop="mainEntityOfPage" href="http://example.com/2021/01/09/cmake%E4%B8%8Ecppcheck%E9%9B%86%E6%88%90/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="image" content="/images/avatar.gif">
      <meta itemprop="name" content="greentree">
      <meta itemprop="description" content="">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="解救Z先生">
    </span>
      <header class="post-header">
        <h2 class="post-title" itemprop="name headline">
          
            <a href="/2021/01/09/cmake%E4%B8%8Ecppcheck%E9%9B%86%E6%88%90/" class="post-title-link" itemprop="url">cmake与cppcheck集成</a>
        </h2>

        <div class="post-meta">
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="far fa-calendar"></i>
              </span>
              <span class="post-meta-item-text">发表于</span>
              

              <time title="创建时间：2021-01-09 23:06:55 / 修改时间：23:18:57" itemprop="dateCreated datePublished" datetime="2021-01-09T23:06:55+08:00">2021-01-09</time>
            </span>

          

        </div>
      </header>

    
    
    
    <div class="post-body" itemprop="articleBody">

      
          <h1 id="CMake与CPPCheck集成"><a href="#CMake与CPPCheck集成" class="headerlink" title="CMake与CPPCheck集成"></a>CMake与CPPCheck集成</h1><img src="/2021/01/09/cmake%E4%B8%8Ecppcheck%E9%9B%86%E6%88%90/hero-image@2x.png" class title="title text" alt="alt text">

<h6 id="CMake集成-（https-blog-csdn-net-weixin-30853329-article-details-96814546）"><a href="#CMake集成-（https-blog-csdn-net-weixin-30853329-article-details-96814546）" class="headerlink" title="CMake集成 （https://blog.csdn.net/weixin_30853329/article/details/96814546）"></a>CMake集成 （<a target="_blank" rel="noopener" href="https://blog.csdn.net/weixin_30853329/article/details/96814546%EF%BC%89">https://blog.csdn.net/weixin_30853329/article/details/96814546）</a></h6><p>Cppcheck 可以理解编译数据库，可以用 CMake 生成这些。例如：</p>
<figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">$ cmake -DCMAKE_EXPORT_COMPILE_COMMANDS=ON</span><br></pre></td></tr></table></figure>
<p>文件 compile_commands.json 在当前文件夹中创建。</p>
<p>现在像这样运行 Cppcheck：</p>
<figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">$ cppcheck --project=compile_commands.json </span><br><span class="line">$ cppcheck --xml --xml-version=<span class="number">2</span> --enable=all ./ <span class="number">2</span>&gt; cppcheck-report.xml</span><br><span class="line">$ cppcheck --xml --xml-version=<span class="number">2</span> --enable=all --project=compile_commands.json / <span class="number">2</span>&gt; cppcheck-report.xml</span><br><span class="line">    </span><br><span class="line"> ## add_definitions(<span class="string">&quot;_DCMAKE_EXPORT_COMPILE_COMMANDS=ON&quot;</span>)</span><br></pre></td></tr></table></figure>
<h6 id="lcov集成-（https-www-jianshu-com-p-a42bbd9de1b7）"><a href="#lcov集成-（https-www-jianshu-com-p-a42bbd9de1b7）" class="headerlink" title="lcov集成 （https://www.jianshu.com/p/a42bbd9de1b7）"></a>lcov集成 （<a target="_blank" rel="noopener" href="https://www.jianshu.com/p/a42bbd9de1b7%EF%BC%89">https://www.jianshu.com/p/a42bbd9de1b7）</a></h6><h6 id="gcov-gcovr-https-github-com-SonarOpenCommunity-sonar-cxx-wiki-Coverage-tracers"><a href="#gcov-gcovr-https-github-com-SonarOpenCommunity-sonar-cxx-wiki-Coverage-tracers" class="headerlink" title="gcov/gcovr (https://github.com/SonarOpenCommunity/sonar-cxx/wiki/Coverage-tracers)"></a>gcov/gcovr (<a target="_blank" rel="noopener" href="https://github.com/SonarOpenCommunity/sonar-cxx/wiki/Coverage-tracers">https://github.com/SonarOpenCommunity/sonar-cxx/wiki/Coverage-tracers</a>)</h6><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">gcovr -r WHERE_SONAR_SCANNER_WILL_RUN -x --object-directory&#x3D;ABSOLUTE_PATH_TO_GCOV_FILES_FOLDER &gt; report.xml</span><br><span class="line"></span><br><span class="line">gcovr -r .&#x2F; -x --object-directory&#x3D;&#x2F;home&#x2F;coresat&#x2F;code&#x2F;hy_c_code &gt; report.xml</span><br></pre></td></tr></table></figure>
<p><strong>Lcov</strong> is a <a target="_blank" rel="noopener" href="https://en.wikipedia.org/wiki/Graphical_user_interface">graphical front-end</a> for gcov.</p>
<p><strong>Gcovr</strong> provides a utility for managing the use of gcov and generating summarized code coverage results.</p>
<p><strong>Gcov</strong> is a <a target="_blank" rel="noopener" href="https://en.wikipedia.org/wiki/Code_coverage">source code coverage</a> analysis and statement-by-statement <a target="_blank" rel="noopener" href="https://en.wikipedia.org/wiki/Profiling_(computer_programming)">profiling</a> tool. Gcov generates exact counts of the number of times each statement in a program is executed and annotates <a target="_blank" rel="noopener" href="https://en.wikipedia.org/wiki/Source_code">source code</a> to add instrumentation. Gcov comes as a standard utility with the <a target="_blank" rel="noopener" href="https://en.wikipedia.org/wiki/GNU_Compiler_Collection">GNU Compiler Collection</a> (GCC) suite.</p>
<p>ps：sonar.sources 是配置指定扫描目录，要注意的是该路径是以sonar-project.properties这个文件所在的目录作为相对路径的！如果是多个目录，用分号隔开 </p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">sonar-scanner \</span><br><span class="line">	-Dsonar.sources&#x3D;.&#x2F;lib,.os_if&#x2F;,.&#x2F;sbs,.&#x2F;ue\</span><br><span class="line">	...</span><br></pre></td></tr></table></figure>
<p>SonarOpenCommunity/sonar-cxx</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">https:&#x2F;&#x2F;github.com&#x2F;SonarOpenCommunity&#x2F;sonar-cxx&#x2F;wiki</span><br></pre></td></tr></table></figure>
<h6 id="SonarQube-configuration-client-side-linux-steps"><a href="#SonarQube-configuration-client-side-linux-steps" class="headerlink" title="SonarQube configuration client side (linux) steps"></a>SonarQube configuration client side (linux) steps</h6><p>1). CMakeLists.txt - it will generate compile_commands.json</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">add_definitions(&quot;-DCMAKE_EXPORT_COMPILE_COMMANDS&#x3D;ON&quot;)</span><br></pre></td></tr></table></figure>
<p>2). init_gcov.sh - it will generate compile_commands.json</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">add -DCMAKE_EXPORT_COMPILE_COMMANDS&#x3D;ON</span><br></pre></td></tr></table></figure>
<p>3). install cppcheck</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">sudo apt-get install cppcheck</span><br></pre></td></tr></table></figure>
<p>4). install sonar-scanner-cli-4.4.0.2170-linux.zip to /home/coresat/sonar-scanner-4.4.0.2170-linux</p>
<p>5). export the path, add below lines into /etc/profile</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">export PATH&#x3D;&#x2F;home&#x2F;coresat&#x2F;sonar-scanner-4.4.0.2170-linux&#x2F;bin:$PATH</span><br></pre></td></tr></table></figure>
<p>6). enable the path by restarting the linux or run below command</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">source .&#x2F;etc&#x2F;profile</span><br></pre></td></tr></table></figure>
<p>7). all done, and run below command</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">.&#x2F;sonarqube.sh</span><br></pre></td></tr></table></figure>
<h6 id="Server-side-configuration"><a href="#Server-side-configuration" class="headerlink" title="Server side configuration"></a>Server side configuration</h6><p>1).  Install JDK11</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">upzip jdk-11.0.8_windows-x64_bin.zip to a local folder</span><br><span class="line">加入 jdk-11.0.8_windows-x64_bin\jdk-11.0.8\bin\ 到环境变量 Path</span><br></pre></td></tr></table></figure>
<p>2). Unzip sonarqube-7.9.4, and run sonarqube-7.9.4/bin/windows-x86-64/StartSonar.bat</p>
<p>3). Install and configure plugins</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">https:&#x2F;&#x2F;github.com&#x2F;SonarOpenCommunity&#x2F;sonar-cxx&#x2F;wiki&#x2F;Running-tools</span><br></pre></td></tr></table></figure>
<p>4). Open <a target="_blank" rel="noopener" href="http://localhost:9000/">http://localhost:9000</a> username=admin; password=admin</p>
<h6 id="SonarQube-Concept"><a href="#SonarQube-Concept" class="headerlink" title="SonarQube Concept"></a>SonarQube Concept</h6><p>Issue</p>
<p>​    1). Bug - An issue that represents something wrong in the code.</p>
<p>​    2). Code Smell - A maintainability-releated issue in the code</p>
<p>​    3). Vulnerabilities - A security-related issue which represents a backdoor for attackers.</p>
<p>Technical Debt - The estimated time required to fix all Maintainability issues/code smells;</p>
<p>Security Hotspot - A security-related issue highlighting a pieces of code that uses a security-sensitive API.</p>
<p>Leak Period - Shortly, leak period is time frame (usually since last release), where specified criteria are measured on newly added code. This allows to focus on quality of fresh code and stop the accumulation of technical debt.</p>
<p>Clean as You Code - means focusing on New Code for maximum Code Quality impact with minimum investment.</p>
<p>Issue Severity - BLOCKER, CRITICAL, MAJOR, MINOR, INFO</p>
<p>lssues lifecycle - Open, Confirmed, Resolved, Reopened, Closed. Resolve as fixed, Resolve as false positive, Resolve as won’t fix.</p>
<p>Cyclomatic Complexity meastures the minimum number of test cases required for full test coverage</p>
<p>Cognitive Complexity is a measure of how diffcult the application is to understand.</p>
<h6 id="Cyclomatic-Complexity（圈复杂度）"><a href="#Cyclomatic-Complexity（圈复杂度）" class="headerlink" title="Cyclomatic Complexity（圈复杂度）"></a>Cyclomatic Complexity（圈复杂度）</h6><p>圈复杂度(Cyclomatic Complexity)是一种代码复杂度的衡量标准。它可以用来衡量一个模块判定结构的复杂程度，数量上表现为独立线性路径条数，也可理解为覆盖所有的可能情况最少使用的测试用例数。圈复杂度大说明程序代码的判断逻辑复杂，可能质量低且难于测试和维护。程序的可能错误和高的圈复杂度有着很大关系。</p>
<p>sudo apt-get install python-pip</p>

      
    </div>

    
    
    
      <footer class="post-footer">
        <div class="post-eof"></div>
      </footer>
  </article>
  
  
  

      
  
  
  <article itemscope itemtype="http://schema.org/Article" class="post-block" lang="zh-CN">
    <link itemprop="mainEntityOfPage" href="http://example.com/2021/01/09/%E8%87%AA%E6%97%8B%E9%94%81spin-lock%E5%92%8Craw-spin-lock/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="image" content="/images/avatar.gif">
      <meta itemprop="name" content="greentree">
      <meta itemprop="description" content="">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="解救Z先生">
    </span>
      <header class="post-header">
        <h2 class="post-title" itemprop="name headline">
          
            <a href="/2021/01/09/%E8%87%AA%E6%97%8B%E9%94%81spin-lock%E5%92%8Craw-spin-lock/" class="post-title-link" itemprop="url">自旋锁spin_lock和raw_spin_lock</a>
        </h2>

        <div class="post-meta">
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="far fa-calendar"></i>
              </span>
              <span class="post-meta-item-text">发表于</span>
              

              <time title="创建时间：2021-01-09 16:35:28 / 修改时间：17:14:27" itemprop="dateCreated datePublished" datetime="2021-01-09T16:35:28+08:00">2021-01-09</time>
            </span>

          

        </div>
      </header>

    
    
    
    <div class="post-body" itemprop="articleBody">

      
          <h1 id="自旋锁spin-lock和raw-spin-lock"><a href="#自旋锁spin-lock和raw-spin-lock" class="headerlink" title="自旋锁spin_lock和raw_spin_lock"></a>自旋锁spin_lock和raw_spin_lock</h1><p>本文不打算详细探究spin_lock的详细实现机制，只是最近对raw_spin_lock的出现比较困扰，搞不清楚什么时候用spin_lock，什么时候用raw_spin_lock，因此有了这篇文章。</p>
<h1 id="1-临界区（Critical-Section）"><a href="#1-临界区（Critical-Section）" class="headerlink" title="1.  临界区（Critical Section）"></a>1.  临界区（Critical Section）</h1><p>我们知道，临界区是指某个代码区间，在该区间中需要访问某些共享的数据对象，又或者是总线，硬件寄存器等，通常这段代码区间的范围要控制在尽可能小的范围内。临界区内需要对这些数据对象和硬件对象的访问进行保护，保证在退出临界区前不会被临界区外的代码对这些对象进行修改。出现以下几种情形时，我们需要使用临界区进行保护：</p>
<ul>
<li>(1)  在可以抢占（preemption）的系统中，两个线程同时访问同一个对象；</li>
<li>(2)  线程和中断同时访问同一个对象；</li>
<li>(3)  在多核系统中(SMP)，可能两个CPU可能同时访问同一个对象；</li>
</ul>
<h1 id="2-自旋锁（spin-lock）"><a href="#2-自旋锁（spin-lock）" class="headerlink" title="2.  自旋锁（spin_lock）"></a>2.  自旋锁（spin_lock）</h1><p>针对单处理器系统，对第一种情况，只要临时关闭系统抢占即可，我们可以使用以下方法：</p>
<figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">preempt_disable();</span><br><span class="line">.....</span><br><span class="line"><span class="comment">// 访问共享对象的代码</span></span><br><span class="line">......</span><br><span class="line">preempt_enable();</span><br></pre></td></tr></table></figure>
<p>同样地，针对单处理器系统，第二种情况，只要临时关闭中断即可，我们可以使用以下方法：</p>
<figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">local_irq_disable();</span><br><span class="line">......</span><br><span class="line"><span class="comment">// 访问共享对象的代码</span></span><br><span class="line">......</span><br><span class="line">local_irq_enable();</span><br></pre></td></tr></table></figure>
<p>那么，针对多处理器的系统，以上的方法还成立么？答案很显然：不成立。</p>
<p>对于第一种情况，虽然抢占被禁止了，可是另一个CPU上还有线程在运行，如果这个线程也正好要访问该共享对象，上面的代码段显然是无能为力了。</p>
<p>对于第二种情况，虽然本地CPU的中断被禁止了，可是另一个CPU依然可以产生中断，如果他的中断服务程序也正好要访问该共享对象，上面的代码段也一样无法对共享对象进行保护。</p>
<p>实际上，在linux中，上面所说的三种情况都可以用自旋锁(spin_lock)解决。基本的自旋锁函数对是：</p>
<ul>
<li>spin_lock(spinlock_t *lock)；</li>
<li>spin_unlock(spinlock_t *lock)；</li>
</ul>
<p>对于单处理器系统，在不打开调试选项时，spinlock_t实际上是一个空结构，把上面两个函数展开后，实际上就只是调用preempt_disable()和preempt_enable()，对于单处理器系统，关掉抢占后，其它线程不能被调度运行，所以并不需要做额外的工作，除非中断的到来，不过内核提供了另外的变种函数来处理中断的问题。</p>
<p>对于多处理器系统，spinlock_t实际上等效于内存单元中的一个整数，内核保证spin_lock系列函数对该整数进行原子操作，除了调用preempt_disable()和preempt_enable()防止线程被抢占外，还必须对spinlock_t上锁，这样，如果另一个CPU的代码要使用该临界区对象，就必须进行自旋等待。</p>
<p>对于中断和普通线程都要访问的对象，内核提供了另外两套变种函数：</p>
<ul>
<li>spin_lock_irq(spinlock_t *lock)；</li>
<li>spin_unlock_irq(spinlock_t *lock)；</li>
</ul>
<p>和：</p>
<ul>
<li>spin_lock_irqsave(lock, flags)；</li>
<li>spin_lock_irqrestore(lock, flags)；</li>
</ul>
<p>我们可以按以下原则使用上面的三对变种函数（宏）：</p>
<ul>
<li>如果只是在普通线程之间同时访问共享对象，使用spin_lock()/spin_unlock()；</li>
<li>如果是在中断和普通线程之间同时访问共享对象，并且确信退出临界区后要打开中断，使用spin_lock_irq()/spin_unlock_irq()；</li>
<li>如果是在中断和普通线程之间同时访问共享对象，并且退出临界区后要保持中断的状态，使用spin_lock_irqsave()/spin_unlock_irqrestore()；</li>
</ul>
<p>其实变种还不止这几个，还有read_lock_xxx/write_lock_xxx、spin_lock_bh/spin_unlock_bh、spin_trylock_xxx等等。但常用的就上面几种。</p>
<h1 id="3-raw-spin-lock"><a href="#3-raw-spin-lock" class="headerlink" title="3.  raw_spin_lock"></a>3.  raw_spin_lock</h1><p>在2.6.33之后的版本，内核加入了raw_spin_lock系列，使用方法和spin_lock系列一模一样，只是参数有spinlock_t变为了raw_spinlock_t。而且在内核的主线版本中，spin_lock系列只是简单地调用了raw_spin_lock系列的函数，但内核的代码却是有的地方使用spin_lock，有的地方使用raw_spin_lock。是不是很奇怪？要解答这个问题，我们要回到2004年，MontaVista Software, Inc的开发人员在邮件列表中提出来一个Real-Time Linux Kernel的模型，旨在提升Linux的实时性，之后Ingo Molnar很快在他的一个项目中实现了这个模型，并最终产生了一个Real-Time preemption的patch。</p>
<p><strong>该模型允许在临界区中被抢占，而且申请临界区的操作可以导致进程休眠等待，这将导致自旋锁的机制被修改，由原来的整数原子操作变更为信号量操作</strong>。当时内核中已经有大约10000处使用了自旋锁的代码，<strong>直接修改spin_lock将会导致这个patch过于庞大，于是，他们决定只修改哪些真正不允许抢占和休眠的地方，而这些地方只有100多处，这些地方改为使用raw_spin_lock</strong>，但是，因为原来的内核中已经有raw_spin_lock这一名字空间，用于代表体系相关的原子操作的实现，于是linus本人建议：</p>
<ul>
<li>把原来的raw_spin_lock改为arch_spin_lock；</li>
<li>把原来的spin_lock改为raw_spin_lock；</li>
<li>实现一个新的spin_lock；</li>
</ul>
<p>写到这里不知大家明白了没？对于2.6.33和之后的版本，我的理解是：</p>
<ul>
<li>尽可能使用spin_lock；</li>
<li>绝对不允许被抢占和休眠的地方，使用raw_spin_lock，否则使用spin_lock；</li>
<li>如果你的临界区足够小，使用raw_spin_lock；</li>
</ul>
<p>对于没有打上Linux-RT（实时Linux）的patch的系统，spin_lock只是简单地调用raw_spin_lock，实际上他们是完全一样的，如果打上这个patch之后，spin_lock会使用信号量完成临界区的保护工作，带来的好处是同一个CPU可以有多个临界区同时工作，而原有的体系因为禁止抢占的原因，一旦进入临界区，其他临界区就无法运行，<strong>新的体系在允许使用同一个临界区的其他进程进行休眠等待，而不是强占着CPU进行自旋操作</strong>。写这篇文章的时候，内核的版本已经是3.3了，主线版本还没有合并Linux-RT的内容，说不定哪天就会合并进来，也为了你的代码可以兼容Linux-RT，最好坚持上面三个原则。</p>

      
    </div>

    
    
    
      <footer class="post-footer">
        <div class="post-eof"></div>
      </footer>
  </article>
  
  
  


  
  <nav class="pagination">
    <span class="page-number current">1</span><a class="page-number" href="/page/2/">2</a><a class="extend next" rel="next" href="/page/2/"><i class="fa fa-angle-right" aria-label="下一页"></i></a>
  </nav>



          </div>
          

<script>
  window.addEventListener('tabs:register', () => {
    let { activeClass } = CONFIG.comments;
    if (CONFIG.comments.storage) {
      activeClass = localStorage.getItem('comments_active') || activeClass;
    }
    if (activeClass) {
      let activeTab = document.querySelector(`a[href="#comment-${activeClass}"]`);
      if (activeTab) {
        activeTab.click();
      }
    }
  });
  if (CONFIG.comments.storage) {
    window.addEventListener('tabs:click', event => {
      if (!event.target.matches('.tabs-comment .tab-content .tab-pane')) return;
      let commentClass = event.target.classList[1];
      localStorage.setItem('comments_active', commentClass);
    });
  }
</script>

        </div>
          
  
  <div class="toggle sidebar-toggle">
    <span class="toggle-line toggle-line-first"></span>
    <span class="toggle-line toggle-line-middle"></span>
    <span class="toggle-line toggle-line-last"></span>
  </div>

  <aside class="sidebar">
    <div class="sidebar-inner">

      <ul class="sidebar-nav motion-element">
        <li class="sidebar-nav-toc">
          文章目录
        </li>
        <li class="sidebar-nav-overview">
          站点概览
        </li>
      </ul>

      <!--noindex-->
      <div class="post-toc-wrap sidebar-panel">
      </div>
      <!--/noindex-->

      <div class="site-overview-wrap sidebar-panel">
        <div class="site-author motion-element" itemprop="author" itemscope itemtype="http://schema.org/Person">
  <p class="site-author-name" itemprop="name">greentree</p>
  <div class="site-description" itemprop="description"></div>
</div>
<div class="site-state-wrap motion-element">
  <nav class="site-state">
      <div class="site-state-item site-state-posts">
          <a href="/archives/">
        
          <span class="site-state-item-count">13</span>
          <span class="site-state-item-name">日志</span>
        </a>
      </div>
      <div class="site-state-item site-state-tags">
        <span class="site-state-item-count">3</span>
        <span class="site-state-item-name">标签</span>
      </div>
  </nav>
</div>



      </div>

    </div>
  </aside>
  <div id="sidebar-dimmer"></div>


      </div>
    </main>

    <footer class="footer">
      <div class="footer-inner">
        

        

<div class="copyright">
  
  &copy; 
  <span itemprop="copyrightYear">2021</span>
  <span class="with-love">
    <i class="fa fa-heart"></i>
  </span>
  <span class="author" itemprop="copyrightHolder">greentree</span>
</div>
  <div class="powered-by">由 <a href="https://hexo.io/" class="theme-link" rel="noopener" target="_blank">Hexo</a> & <a href="https://muse.theme-next.org/" class="theme-link" rel="noopener" target="_blank">NexT.Muse</a> 强力驱动
  </div>

        








      </div>
    </footer>
  </div>

  
  <script src="/lib/anime.min.js"></script>
  <script src="/lib/velocity/velocity.min.js"></script>
  <script src="/lib/velocity/velocity.ui.min.js"></script>

<script src="/js/utils.js"></script>

<script src="/js/motion.js"></script>


<script src="/js/schemes/muse.js"></script>


<script src="/js/next-boot.js"></script>




  















  

  

</body>
</html>
